在调整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的底部框架你会发现它很棒。