繁体   English   中英

在调整Jframe大小之前,JPanel不会更新

[英]JPanel doesn't update until resize Jframe

我子类化JPanel以覆盖paintComponent(Graphics),我想在jframe中将图像绘制到jpanel上。

但是直到我更改了jframe的大小,我的图像才出现。 这是我的代码:

public class ImagePanel extends JPanel{

    public void setImage(BufferedImage bi)
    {
        image = bi;
        revalidate();
    }

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        if(image != null)
        {
            g.drawImage(image, 0, 0, this);
        }
    }
}

验证是否添加组件并调用pack() setVisible() 之后调用setVisible() ,如本示例中所述 您可能还需要采用适当的布局 调用repaint()如建议在这里 ,可以解决症状,但不是根本原因。

如果要“刷新” JPanel,则应调用repaint(),后者将调用paintComponent()。 这应该可以解决您的问题:

public void setImage(BufferedImage bi)
{
    image = bi;
    EventQueue.invokeLater(new Runnable()
    {
        public void run()
        {
            repaint();
        }
    });
}

使用EDT更新和更改GUI的良好做法。 如果您有兴趣,这里是EDT的更多信息:

事件分派线程如何工作?

不需要从EDT调用repaint 如果要更改GUI,例如将文本设置为JLabel,则它应位于EDT内。 以下是有关在EDT之外可以调用的内容的更多信息(由nIcE cOw提供):

在EDT之外可以安全地使用Component.repaint()吗?

看一下JPanel.add() 的文档 ,它是从java.awt.Container继承的:

将指定的组件追加到此容器的末尾。 这是addImpl(java.awt.Component,java.lang.Object,int)的便捷方法。 此方法更改与布局有关的信息,因此使组件层次结构无效。 如果已经显示了容器,则此后必须验证层次结构才能显示添加的组件。

重点已添加。

因此,如果在显示容器对其进行修改,则必须调用validate()使其显示。 仅调用repaint()是不够的。 您可能已经注意到,调用setVisible(true)也可以; 这是因为它在内部调用validate()

我有同样的问题,可以通过调用setVisible(true)来解决。 我正在使用的JFrame。

示例:如果您的JFrame在使用后没有更新:

jframe.setContentPane(new MyContentPane());

修复:

jframe.setContentPane(new MyContentPane());
jframe.setVisible(true);

我知道即使您的JFrame已经可见,执行此操作听起来也很愚蠢,但这是我到目前为止找到的解决此问题的唯一方法(上面提出的解决方案对我不起作用)。

这是一个完整的例子。 运行它,然后取消注释“ f.setVisible(true);” 类Panel1和Panel2中的说明,您将看到区别。 不要忘记导入(对于自动导入,请按Ctrl + Shift + O)。

主类:

public class Main {
    private static JFrame f;
    public static void main(String[] args) {
        f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setContentPane(new Panel1(f));
        f.pack();    
        f.setVisible(true);
    }
}

Panel1类:

public class Panel1 extends JPanel{
    private JFrame f;
    public Panel1(JFrame frame) {
        f = frame;
        this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
        JButton b = new JButton("Panel 1");
        b.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                f.setContentPane(new Panel2(f));
                // Uncomment the instruction below to fix GUI "update-on-resize-only" problem
                //f.setVisible(true);
            }
        });
        add(b);
    }
}

Panel2类:

public class Panel2 extends JPanel{
    private JFrame f;
    public Panel2(JFrame frame) {
        f = frame;
        this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
        JButton b = new JButton("Panel 2");
        b.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                f.setContentPane(new Panel1(f));
                // Uncomment the instruction below to fix GUI "update-on-resize-only" problem
                //f.setVisible(true);
            }
        });
        add(b);
    }
}

希望能有所帮助。

问候。

我也有同样的问题,但我找到了解决方案。 只需在顶部创建一个jframe对象,然后在底部调用jframe方法,例如jf.pack()jf.setVisible()jf.setSize()jf.setDefaultCloseOpetion()应该位于添加的所有UI的底部框架,您会发现它很棒。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM