我将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);
}
}
}
答案 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提供):
答案 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的底部,您会发现它工作得很好。