JPanel 添加到 JFrame 后如何更改?

How can a JPanel be changed after added to JFrame?

我创建了一个 JPanel 的子类来显示图像。我在 JFrame 的构造函数中实例化它并将其添加到该 JFrame。这非常有效。然后我添加了一个带有 ActionListener 的按钮来更改该图像。我的问题是 JFrame 不会更新,尽管我已经尝试重新绘制等

JPanel的子类:

public class ImagePanel extends JPanel {

    BufferedImage bf;
    public ImagePanel(String dateiname)
    {
        try {
            bf = ImageIO.read(new File(dateiname));


        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void paint(Graphics g)
    {
        g.drawImage(bf.getScaledInstance(300,200,1),0,0,null );
    }
}

JFrame基本就是这样

public class Hauptfenster extends JFrame {

private JButton changeImage;
private JPanel buttonPanel;
private ImagePanel ip;


public Hauptfenster {

ip = new ImagePanel("first_image.jpg");

buttonPanel = new JPanel();
buttonPanel.add(changeImage);

changeImage.addActionListener((e) -> {

ip = new ImagePanel("new_image.jpg");
ip.setVisible(true);


});


this.add(buttonPanel);
this.add(ip);
this.setVisible(true);

}

}

为什么 ActionListener 中的方法不更新 JFrame Hauptfenster 中的 ip 组件?

当您执行 ip = new ImagePanel("new_image.jpg"); 时,您正在创建一个与当前布局无关的全新 ImagePanel。你可以。

remove(ip);
ip = new ImagePanel("new_image.jpg");
add(ip);
repaint();

另一种方法是只更改缓冲图像。

将以下方法添加到您的图像面板。

public void loadImage(String dateiname) {
    try {
        bf = ImageIO.read(new File(dateiname));


    } catch (IOException e) {
        e.printStackTrace();
    }
}

然后在你的动作侦听器中。

ip.loadNewImage("new_image.jpg");
ip.repaint();

虽然你的代码中有很多坏习惯。

例如,覆盖 paintComponent 而不是 paint,它应该看起来像。

@Override
public void paintComponent(Graphics g){
    super.paintComponent(g);
    g.drawImage(bf.getScaledInstance(300,200,1),0,0,null );
}

这样透明度将得到正确处理。

您不应该扩展 JFrame,您应该只创建一个 JFrame。

添加组件时,会涉及布局管理器。意识到这一点并相应地处理事情是很好的。我会将您的构造函数更改为。

public Hauptfenster() {

    JFrame frame = new JFrame();
    ip = new ImagePanel("first_image.jpg");
    buttonPanel = new JPanel();
    changeImage = new JButton("change image");
    buttonPanel.add(changeImage);

    changeImage.addActionListener((e) -> {
        frame.remove(ip);
        ip = new ImagePanel("new_image.jpg");
        frame.add(ip, BorderLayout.CENTER);
        frame.repaint();
    });
    frame.add(buttonPanel, BorderLayout.SOUTH);
    frame.add(ip, BorderLayout.CENTER);
    frame.setVisible(true);
}

如果您需要更多帮助,您需要实际使您的示例可编译。目前错误太多。