在框架内重新绘制JPanel

Jos*_*hua 5 java animation swing jpanel

我在框架内有一个JPanel.JPanel的内容应该在每次调用时更新paintComponent(调用方式repaint()),但是当我按照下面的方式调用时,我只看到一个白色的窗口.(请原谅那些破损的缩进,Eclipse会使用标签做各种奇怪的事情.)

private static void handleGUI() 
{       
    JFrame frame = new JFrame("Animation");
    frame.setPreferredSize(new Dimension(100, 100));

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    Board b = new Board();

    frame.getContentPane().add(b);

    frame.pack();
    frame.setVisible(true);

    while(true)
    {
        System.out.println("Repainting panel");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }
        b.repaint();
    }
}

public class Board extends JPanel
{
public Board() { t=0; }

    private int t;

public void paintComponent(Graphics g) 
{
    super.paintComponent(g);

    ++t;

    /* Variables snipped */

    g.setColor(Color.white);
    g.drawOval(0, 0, width, height);

    BufferedImage image = ImageIO.read(new File(imagePath));
    g.drawImage(image, x(t), y(t));
    /* There's some more image and rectangle drawing ahead */
}
Run Code Online (Sandbox Code Playgroud)

}

Hov*_*els 6

你的代码有几个问题,上面已经提到了一个问题(1 + rep - 虽然它看起来好像你现在在paintComponent方法中有代码做了绘图),你的paintComponent方法是有缺陷的,但不仅如此你在Swing主线程EDT中有一个while(true)循环和一个Thread.sleep,这将使Swing和整个GUI进入休眠状态.最好使用Swing Timer.另外,你说,

每次调用paintComponent(由repaint()调用)都应该更新JPanel的内容,

您确定要将程序逻辑放在paintComponent方法中吗?这通常是不受欢迎的,因为程序员没有完全控制何时调用此方法.它可能在您调用重绘时调用(但不总是),并且可能由于来自操作系统的消息而在您不希望调用它时调用.

此外,您永远不想读取paintComponent方法中的文件,因为这会将您的绘画减慢到一个cawl.

我建议这些改变:

1)创建一个周期为1000的Swing Timer,并在其ActionListener的actionPerformed方法中读入您的图像(如果图像有任何显着大小,最好在后台线程中)并将图像读入类字段,例如称为图像.

2)在同一个Timer的actionPerformed方法中,增加t.

3)读入图像后,在绘图JPanel上调用重绘,并让绘图JPanel使用图像变量绘制图像.如果您使用后台线程读取图像,请小心,因为您需要在完全读入图像时让此线程通知GUI.如果使用SwingWorker执行此操作,则可以添加侦听的PropertyChangeListener到SwingWorker的状态值并在此更改为StateValue.DONE时触发.

如果其中任何一项不清楚或令人困惑,请要求澄清.

编辑:如果图像不是太大,您可能希望一次读取所有图像,或者在需要一堆时进行批量读取.在使用它们之前,不需要立即读取图像.