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

nau*_*svn 17 java user-interface swing paintcomponent

我将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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

tra*_*god 18

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


Joh*_*ohn 7

如果你想"刷新"JPanel,那么你应该调用repaint(),它将调用你的paintComponent().这应该可以解决您的问题:

public void setImage(BufferedImage bi)
{
    image = bi;
    EventQueue.invokeLater(new Runnable()
    {
        public void run()
        {
            repaint();
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

使用EDT更新和更改GUI的良好做法.如果您有兴趣,请提供有关EDT的更多信息:

事件派发线程如何工作?

repaint不需要从EDT调用.如果您正在更改GUI,例如将文本设置为JLabel,则它应该位于EDT内部.关于在EDT之外可以称之为什么的更多信息(由nIcE cOw提供):

在EDT之外安全使用Component.repaint()?

  • +1为有价值的输入.只是一个建议,不需要在EDT中放置`repaint()`调用,因为从任何线程调用`repaint()`都是安全的,如[here]所述(http://stackoverflow.com/questions/9786497/safe -to-使用组分-重绘-外EDT/9786598#9786598) (2认同)

Nat*_*ami 7

看看该文档JPanel.add(),它继承自java.awt.Container:

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

强调补充说.

因此,如果已经显示Container 之后修改它,则必须调用validate()它才能显示它.只是调用repaint()是不够的.您可能已经注意到呼叫setVisible(true)也有效; 这是因为它在validate()内部调用.