Java JPanel没有';在调整Jframe的大小之前,请不要更新
我将JPanel子类化以覆盖paintComponent(图形),我希望在jframe中在JPanel上绘制一个图像 但直到我改变了jframe的尺寸,我的图像才显示出来。 这是我的代码:Java JPanel没有';在调整Jframe的大小之前,请不要更新,java,swing,user-interface,paintcomponent,Java,Swing,User Interface,Paintcomponent,我将JPanel子类化以覆盖paintComponent(图形),我希望在jframe中在JPanel上绘制一个图像 但直到我改变了jframe的尺寸,我的图像才显示出来。 这是我的代码: public class ImagePanel extends JPanel{ public void setImage(BufferedImage bi) { image = bi; revalidate(); } @Override
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);
}
}
}
如果要“刷新”JPanel,则应调用repaint(),这将调用paintComponent()。这将解决您的问题:
public void setImage(BufferedImage bi)
{
image = bi;
EventQueue.invokeLater(new Runnable()
{
public void run()
{
repaint();
}
});
}
使用EDT更新和更改GUI是一种很好的做法。如果您感兴趣,这里有更多关于EDT的信息:
重新绘制
不需要从EDT调用。如果要更改GUI,例如将文本设置为JLabel,则它应该位于EDT内部。以下是EDT之外的更多信息(由nIcE cOw提供):
验证是否在添加组件和调用后调用了
setVisible()
,如本相关章节所述。您可能还需要采取适当的措施。按照建议调用repaint()
,可能会修复症状,但不会修复根本原因。我也有同样的问题,并通过调用setVisible(true)修复了它;我使用的JFrame
示例:如果您的JFrame在使用后未更新:
jframe.setContentPane(new MyContentPane());
用以下方法修复它:
jframe.setContentPane(new MyContentPane());
jframe.setVisible(true);
我知道这样做听起来很傻,即使你的JFrame已经是可见的,但这是迄今为止我找到的唯一解决这个问题的方法(上面提出的解决方案对我不起作用)
这是一个完整的例子。运行它,然后取消注释类Panel1和Panel2中的“f.setVisible(true);”指令,您将看到它们的区别。不要忘记导入(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);
}
}
第1组类别:
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);
}
}
第2组类别:
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);
}
}
希望有帮助
问候。看看它从java.awt.Container
继承的JPanel.add()
:
将指定的组件追加到此容器的末尾。这是addImpl(java.awt.Component、java.lang.Object、int)的一种方便方法。
此方法会更改布局相关信息,因此,会使组件层次结构无效。如果容器已经显示,则此后必须验证层次结构,以便显示添加的组件。
重点补充
因此,如果在容器已经显示之后修改它,则必须调用
validate()
,才能显示它。仅仅调用repaint()
是不够的。您可能已经注意到调用setVisible(true)
也可以工作;这是因为。我也有同样的问题,但我找到了解决办法。只需在顶部创建一个jframe
对象,并在底部调用jframe
方法,比如jf.pack()
,jf.setVisible()
,jf.setDefaultCloseOpetion()
应该位于该框架中添加的所有UI的底部,您会发现它工作得很好 有价值的输入+1。只是一个建议,不需要在EDT中调用repaint()
,因为从任何线程调用repaint()
都是安全的,正如“具有UI委托的Swing组件的子类…应该调用super.paintComponent()
”——所述。太棒了!不知道为什么会这样,但这是唯一解决我问题的办法。在此之前,我做过这样的工作:Dimension size=frame.getSize();布尔最大化=frame.getExtendedState()==JFrame.maximized\u两者;frame.setSize(新维度((int)size.getWidth()-1,(int)size.getHeight()-1));if(最大化)frame.setExtendedState(JFrame.maximized_两者);else frame.setSize(大小);你的答案是非常,非常干净和方式少黑客。谢谢@dberm22实际上,不需要进行黑客攻击(至少在本例中没有,没有使用可能不同大小的图像检查原始图像,也没有使用可能很棘手的扩展大小状态):设置contentPane是对框架容器层次结构的修改,因此需要对框架进行重新验证。使用revalidate()
可以获得更好的结果validate()
执行此操作,但不会更改尺寸以适应添加的新组件。