20

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

5 回答 5

21

验证您是否在添加组件和调用setVisible() pack()调用,如相关示例中所述。您可能还需要采用适当的布局repaint()如此处建议调用可能会解决症状,但不能解决根本原因。

于 2012-06-17T16:52:37.607 回答
8

如果你想“刷新”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() 安全吗?

于 2012-06-17T08:20:01.790 回答
8

查看它的文档JPanel.add()它继承自java.awt.Container

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

重点补充。

因此,如果您在 Container已显示后对其进行修改,则必须调用validate()它才能显示。仅仅调用repaint()是不够的。您可能已经注意到呼叫setVisible(true)也有效;这是因为它在内部调用validate().

于 2015-08-22T11:34:40.097 回答
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);
    }
}

希望有帮助。

问候。

于 2013-07-12T00:29:04.707 回答
1

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

于 2018-06-01T02:04:04.580 回答