【问题标题】:How can a JPanel be changed after added to JFrame?JPanel 添加到 JFrame 后如何更改?
【发布时间】:2021-12-16 02:01:46
【问题描述】:

我创建了一个 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 组件?

【问题讨论】:

    标签: java swing jframe jpanel


    【解决方案1】:

    当您执行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);
    }
    

    如果您需要更多帮助,您需要真正使您的示例可编译。现在错误太多了。

    【讨论】:

    • 谢谢,这对您有很大帮助,最后更改 BufferedImage 或删除和添加 ImagePanel 的新实例的两种方法都有效。我的计划是在 JFrame 中实现一种显示。由于图像需要一些时间来缩放,swing 在这里异步工作吗?尽管我仍在学习中,请随意在代码中提及我的坏习惯
    • Swing 在一个线程上完成所有事情,即事件调度线程 (EDT)。如果缩放需要很长时间,您可能会在不同的线程上加载和缩放图像。也许是一个 SwingWorker,这样当你绘画时你就不必每次都缩放(就像你现在所做的那样。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多