打印到控制台更新视觉效果? - Java

时间:2017-03-22 19:40:47

标签: java multithreading swing bufferedimage

对于大学项目,我的任务是用Java制作冒险游戏。我已经使用过线程和swing库等,但现在我遇到了一个问题。

// The following is in the constructor of a subclass of JPanel
gameViewThread = new Thread(() -> {
    double previous = System.currentTimeMillis();
        double lag = 0.0;
        double current;
        double elapsed;
        while(true){
            current = System.currentTimeMillis();
            elapsed = current - previous;
            previous = current;
            lag += elapsed;
            System.out.println("Checking up on stuff...");
            while(OverworldMap.initialised && lag >= 17) {
                generateBackground();
                lag -= 17;
            }
        }
});

在上面粘贴的代码的第11行,我有一个打印声明,我想删除。 (我不想用不需要的信息充斥控制台) 但是,当我删除该语句时,视觉效果不会更新。 我已经一次又一次地测试过,我确保OverworldMap.initialised返回true。在调试模式下运行代码时,我确保generateBackground()运行。所以对我来说,看起来视觉效果只是没有更新,除非你醒来'系统。

注意:generateBackground()在BufferedImage变量中生成并保存图像,而repaint()确保将图像绘制在正确的位置。 (repaint()在主线程中每秒调用30次)这两种方法都有效。在我尝试将背景生成(从Pokemon Fire Red o / e中思考平铺动画)转移到另一个线程之前,他们工作了。 (我不希望逻辑和动画相互干扰。(我的帧速率很低))

1 个答案:

答案 0 :(得分:1)

因为您正在尝试从主线程更新UI。它不会那样工作。尝试在程序中使用SwingUtilities.invokeLater()方法。

以下代码段可能很有用:

public void init() {
    gameViewThread = new Thread(() -> {
        double previous = System.currentTimeMillis();
        double lag = 0.0;
        double current;
        double elapsed;
        while (true) {
            current = System.currentTimeMillis();
            elapsed = current - previous;
            previous = current;
            lag += elapsed;
            //System.out.println("Checking up on stuff...");
            while (OverworldMap.initialised && lag >= 17) {
                updateUI();
                //generateBackground();
                lag -= 17;
            }
        }
    });
}


public void updateUI() {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            // All swing UI update code here
            generateBackground();                    
        }
    });
}

PS:另外,请记住,不要为你的线程使用run()方法。您应该调用start()方法使其运行。首先,在构造函数中调用我提供的init()方法以及代码中的某个地方(也可能在你的构造函数中)使用gameViewThread.start()来启动你的线程。