如何使用JFileChooser在JPanel中显示图像

3

我正在尝试使用菜单栏,使用户可以选择文件并在JPanel中显示该文件,图像应该完全适合JPanel。但是JFileChooser在从对话框中成功选择文件后不会显示任何内容。我尝试参考了许多链接:如何向JPanel添加图像?使用Java Swing浏览图像文件并将其显示出来,但没有任何作用,请帮忙解决。以下是我的代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;

class Main {
private JFrame j;
private JMenu jmenu;
private JMenuBar jbar;
private JMenuItem jmi, jexit;
private JPanel jpanel, jpanelbar;
private JButton jpre, jnext;
JLabel image;
ImageIcon ic;
Image img;

Main() {
    j = new JFrame("Image Viewer");
    j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    // j.setExtendedState(Frame.MAXIMIZED_BOTH);
    // j.setLocationRelativeTo(null);
    j.setLocationByPlatform(true);
    j.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    jpanel = new JPanel();
    c.anchor = GridBagConstraints.PAGE_START;
    c.fill = GridBagConstraints.HORIZONTAL;
    c.gridx = c.gridy = 0;
    c.gridwidth = 2;
    // c.weightx=0.1;
    c.weighty = 0.1;
    c.ipady = 600;
    c.insets = new Insets(5, 5, 10, 5);
    // jpanel.setBackground(Color.BLACK);
    j.add(jpanel, c);

    jpanelbar = new JPanel();
    jpanelbar.setBackground(Color.red);
    c.weightx = 0.1;
    c.gridx = 0;
    c.gridy = 1;
    c.fill = GridBagConstraints.HORIZONTAL;
    c.insets = new Insets(5, 5, 5, 5);
    c.ipady = 150;
    j.add(jpanelbar, c);

    jpanelbar.setLayout(new GridBagLayout());
    GridBagConstraints x = new GridBagConstraints();
    jpre = new JButton("Previous");
    x.gridx = 0;
    x.gridy = 0;
    x.gridwidth = 1;
    x.weightx = 0.1;
    // x.insets=new Insets(5,5,5,5);
    // x.fill=GridBagConstraints.NONE;
    jpanelbar.add(jpre, x);

    jnext = new JButton("Next");
    x.gridx = 1;
    jpanelbar.add(jnext, x);

    // Creating Menu
    jbar = new JMenuBar();
    jmenu = new JMenu("File");
    jmi = new JMenuItem("Open");
    jmi.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent ae) {
            JFileChooser fc = new JFileChooser();
            int result = fc.showOpenDialog(null);
            if (result == JFileChooser.APPROVE_OPTION) {
                File file = fc.getSelectedFile();
                String sname = file.getName();
                image = new JLabel("", new ImageIcon(sname), JLabel.CENTER);
                jpanel.add(image, BorderLayout.CENTER);
            }
        }
    });
    jexit = new JMenuItem("Exit");
    jexit.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent ae) {
            System.exit(0);
        }
    });
    jmenu.add(jmi);
    jmenu.add(jexit);
    jbar.add(jmenu);
    j.setJMenuBar(jbar);

    j.setSize(800, 600);
    j.setResizable(false);
    j.setVisible(true);
}

public static void main(String s[]) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            new Main();
        }
    });
}
}

更新后的代码如下:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;

class Main {
private JFrame j;
private JMenu jmenu;
private JMenuBar jbar;
private JMenuItem jmi, jexit;
private JPanel jpanel, jpanelbar;
private JButton jpre, jnext;
JLabel image;
ImageIcon ic;
Image img;

Main() {
    j = new JFrame("Image Viewer");
    j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    // j.setExtendedState(Frame.MAXIMIZED_BOTH);
    // j.setLocationRelativeTo(null);
    j.setLocationByPlatform(true);
    j.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    jpanel = new JPanel();
    c.anchor = GridBagConstraints.PAGE_START;
    c.fill = GridBagConstraints.HORIZONTAL;
    c.gridx = c.gridy = 0;
    c.gridwidth = 2;
    // c.weightx=0.1;
    c.weighty = 0.1;
    c.ipady = 600;
    c.insets = new Insets(5, 5, 10, 5);
    // jpanel.setBackground(Color.BLACK);
    j.add(jpanel, c);

    jpanelbar = new JPanel();
    jpanelbar.setBackground(Color.red);
    c.weightx = 0.1;
    c.gridx = 0;
    c.gridy = 1;
    c.fill = GridBagConstraints.HORIZONTAL;
    c.insets = new Insets(5, 5, 5, 5);
    c.ipady = 150;
    j.add(jpanelbar, c);

    jpanelbar.setLayout(new GridBagLayout());
    GridBagConstraints x = new GridBagConstraints();
    jpre = new JButton("Previous");
    x.gridx = 0;
    x.gridy = 0;
    x.gridwidth = 1;
    x.weightx = 0.1;
    // x.insets=new Insets(5,5,5,5);
    // x.fill=GridBagConstraints.NONE;
    jpanelbar.add(jpre, x);

    jnext = new JButton("Next");
    x.gridx = 1;
    jpanelbar.add(jnext, x);

    // Creating Menu
    jbar = new JMenuBar();
    jmenu = new JMenu("File");
    jmi = new JMenuItem("Open");
    jmi.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent ae) {
            JFileChooser fc = new JFileChooser();
            int result = fc.showOpenDialog(null);
            if (result == JFileChooser.APPROVE_OPTION) {
                File file = fc.getSelectedFile();
                String sname = file.getName();
                image = new JLabel("", new ImageIcon(sname), JLabel.CENTER);
                jpanel.add(image, BorderLayout.CENTER);
                jpanel.revalidate();
                jpanel.repaint();
            }
        }
    });
    jexit = new JMenuItem("Exit");
    jexit.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent ae) {
            System.exit(0);
        }
    });
    jmenu.add(jmi);
    jmenu.add(jexit);
    jbar.add(jmenu);
    j.setJMenuBar(jbar);

    j.setSize(800, 600);
    j.setResizable(false);
    j.setVisible(true);
}

public static void main(String s[]) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            new Main();
        }
    });
}
}
3个回答

8
我已经让你的代码半成功了,但有很多问题需要解决。
  • 我在你的jpanel中添加了一个BorderLayout。

  • 我把图像的初始化移出了你的打开菜单动作监听器,就像Reimeus告诉你的那样。

  • 我使用ImageIO读取图像。

你最终会需要这个答案。 将图片调整大小以适应JLabel

这是我版本的你的代码。愿上帝怜悯你的灵魂。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

class Main {
    private JFrame      j;
    private JMenu       jmenu;
    private JMenuBar    jbar;
    private JMenuItem   jmi, jexit;
    private JPanel      jpanel, jpanelbar;
    private JButton     jpre, jnext;
    JLabel              image;
    ImageIcon           ic;
    Image               img;

    Main() {
        j = new JFrame("Image Viewer");
        j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // j.setExtendedState(Frame.MAXIMIZED_BOTH);
        // j.setLocationRelativeTo(null);
        j.setLocationByPlatform(true);
        j.setLayout(new GridBagLayout());

        GridBagConstraints c = new GridBagConstraints();
        jpanel = new JPanel();
        jpanel.setLayout(new BorderLayout());
        image = new JLabel(" ");
        jpanel.add(image, BorderLayout.CENTER);

        c.anchor = GridBagConstraints.PAGE_START;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.gridx = c.gridy = 0;
        c.gridwidth = 2;
        // c.weightx=0.1;
        c.weighty = 0.1;
        c.ipady = 600;
        c.insets = new Insets(5, 5, 10, 5);
        // jpanel.setBackground(Color.BLACK);
        j.add(jpanel, c);

        jpanelbar = new JPanel();
        jpanelbar.setLayout(new GridBagLayout());
        jpanelbar.setBackground(Color.red);

        GridBagConstraints x = new GridBagConstraints();
        jpre = new JButton("Previous");
        x.gridx = 0;
        x.gridy = 0;
        x.gridwidth = 1;
        x.weightx = 0.1;
        // x.insets=new Insets(5,5,5,5);
        // x.fill=GridBagConstraints.NONE;
        jpanelbar.add(jpre, x);

        jnext = new JButton("Next");
        x.gridx = 1;
        jpanelbar.add(jnext, x);

        c.weightx = 0.1;
        c.gridx = 0;
        c.gridy = 1;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.insets = new Insets(5, 5, 5, 5);
        c.ipady = 150;
        j.add(jpanelbar, c);

        // Creating Menu
        jbar = new JMenuBar();
        jmenu = new JMenu("File");
        jmi = new JMenuItem("Open");
        jmi.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                JFileChooser fc = new JFileChooser();
                int result = fc.showOpenDialog(null);
                if (result == JFileChooser.APPROVE_OPTION) {
                    File file = fc.getSelectedFile();
                    try {
                        image.setIcon(new ImageIcon(ImageIO.read(file)));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        jexit = new JMenuItem("Exit");
        jexit.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                System.exit(0);
            }
        });
        jmenu.add(jmi);
        jmenu.add(jexit);
        jbar.add(jmenu);
        j.setJMenuBar(jbar);

//      j.setSize(800, 600);
        j.pack();
        j.setResizable(true);
        j.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new Main();
            }
        });
    }
}

这段代码会生成“不支持的图像类型”错误。有什么解决方法吗? - Rubaiyat Jahan Mumu

4

在渲染图像后,使用file对象上的getAbsolutePath()而不是getName(),并调用repaint()revalidate()。以下代码应该解决您的问题:

jmi.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent ae) {
        JFileChooser fc = new JFileChooser();
        int result = fc.showOpenDialog(null);
        if (result == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            String sname = file.getAbsolutePath(); //THIS WAS THE PROBLEM
            image = new JLabel("", new ImageIcon(sname), JLabel.CENTER);
            jpanel.add(image, BorderLayout.CENTER);
            jpanel.revalidate(); //ADD THIS AS WELL
            jpanel.repaint();  //ADD THIS AS WELL
        }
    }
});

嘿!谢谢。这样做确实起作用了。但是你能否请解释一下你具体做了什么?拜托了。 - crazy4
1
你之前使用了 file.getName(),这会使得渲染过程在当前目录中查找图像。我将其更改为 file.getAbsolutePath()。除此之外,正如 @Reimeus 所提到的,你应该调用 revalidate() 和/或 repaint() 以使 UI 更改生效。如果解决了你的问题,请将其标记为答案。 - Mubin
现在,调用repaint()和revalidate()后,下方面板和按钮已经消失了。为什么?我想在不丢失它们的情况下显示图像。 - crazy4
如果图像的大小大于框架的大小,则会发生这种情况。请使用较小的图像进行测试。要了解如何调整图像大小以适应JLabel,请参阅此链接:https://dev59.com/dGQo5IYBdhLWcg3wE78J - Mubin
我已经尝试过使用较小的图像,甚至是分辨率为110x25像素的图像。但是下方的按钮仍然没有出现。 - crazy4
c.weighty = 0.1; c.ipady = 600; //这是问题所在 c.insets = new Insets(5, 5, 10, 5); j.add(jpanel, c); 你正在要求 jpanel 垂直方向上填充 600 个单位,而 JFrame f 的大小也设置为了 600。这就是为什么南端的组件超出了框架的原因。将 c.ipady 减小到 400 左右,你就会看到原因所在。否则,在添加图像后调用 f.pack(),它将自动调整所有组件的大小。 - Mubin

2

您需要调用

jpanel.revalidate();
jpanel.repaint();

在将JLabel image添加到jpanel后,为什么不直接在启动时添加JLabel,并使用setIcon来设置Image呢?请注意保留HTML标签。

在添加了这些行之后,它仍然没有显示。而且我也不理解你指定的第二种方法。 - crazy4
repaint自JDK 1.0以来就存在了。你能发布一下你更新后的代码吗? - Reimeus
@crazy4,当revalidate调整jpanel面板大小时,您的按钮会消失。如果您调用j.pack(),您将看到首选大小。问题出在大的ipady设置上 - 在重新验证后,按钮面板被推出了JFrame的边界之外。 - Reimeus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接