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

我将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); } } } 

validation添加组件并调用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的更多信息:

事件派发线程如何工作?

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

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

看一下JPanel.add() 的文档 ,它inheritance自java.awt.Container

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

强调补充说。

因此,如果已经显示Container 之后修改它,则必须调用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的底部框架你会发现它很棒。