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

时间:2012-06-17 07:58:52

标签: java swing user-interface 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);
        }
    }
}

5 个答案:

答案 0 :(得分:18)

验证您在添加组件并调用pack()之后调用setVisible() ,如相关example中所述。您可能还需要采用适当的layout。按建议here调用repaint()可能会修复症状但不会导致根本原因。

答案 1 :(得分:7)

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

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

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

How does the event dispatch thread work?

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

Safe to use Component.repaint() outside EDT?

答案 2 :(得分:7)

查看JPanel.add()的{​​{3}},它继承自java.awt.Container

  

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

强调增加。

因此,如果您在之后修改了一个容器,那么必须调用validate()才能显示它。仅仅调用repaint()是不够的。您可能已经注意到调用setVisible(true)也有效;这是因为the docs

答案 3 :(得分:3)

我有同样的问题并通过调用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);
    }
}

希望有所帮助。

问候。

答案 4 :(得分:1)

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