更新GUI会产生闪烁效果

时间:2011-11-22 09:20:26

标签: java multithreading swing game-loop

我目前有一个JFrame,在它的内容窗格中,我以60帧/秒的速度从游戏循环中绘制图像。这很好,但在右侧,我现在有更多的Swing元素,我想在选择内容窗格的某些部分时显示一些信息。该部分是静态GUI,不使用游戏循环。

我正在以这种方式更新它:

public class InfoPanel extends JPanel implements Runnable {
    private String titelType = "type: ";
    private String type;
    private JLabel typeLabel;
    private ImageIcon icon;

    public void update() {
        if (this.icon != null)
            this.typeLabel.setIcon(this.icon);

        if(this.type != null || this.type != "")
            this.typeLabel.setText(this.titelType + this.type);
        else
            this.typeLabel.setText("");
    }

    public void run() {
        try {
            Thread.sleep(150);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        this.update();
    }

(此方法仅在玩家实际移动时调用,因此它只调用一次 - 而不是每秒60次)

我注意到,当从游戏循环中调用此update()方法时,我会得到闪烁效果。我认为这是因为更新UI需要一些时间,所以我决定把它放在一个新的线程中。这减少了闪烁,但没有解决。

接下来,我决定给新线程低优先级,因为屏幕的一部分每秒重绘60次更为重要。这再次减少了闪烁,但它仍然发生了。然后,我决定在调用update() - 方法之前在新线程中使用Thread.sleep(150);,这样就完全解决了对我系统的闪烁效应。

但是,在其他系统上运行时,它仍然会发生。不像以前那样频繁(可能每20秒一次),但它仍然很烦人。显然,只是在另一个线程中更新UI并不能解决问题。

任何想法如何完全消除闪烁?

2 个答案:

答案 0 :(得分:4)

调用update()中的SwingUtilities.invokeAndWait()停止线程并更新EDT中的用户界面。

答案 1 :(得分:3)

问题是您使用Thread.sleep(int),在使用EventDispatchTread Concurency in Swingexample演示冻结GUI的Thread.sleep(int)期间停止并冻结GUI ,example for Runnable #Thread

如果你想延迟Swing中的任何内容,那么最好的方法是实现javax.swing.Timer