【问题标题】:Using Timer to repaint in the fixed time then continuing calculation使用Timer在固定时间内重绘然后继续计算
【发布时间】:2017-11-06 10:38:13
【问题描述】:

目前,我正在制作一个用于图形可视化的 Java 程序 Prim 的算法来寻找最小生成树。

Here is the image of my program's output

while(condition){
    //Find the min vertex and min edges
    Vertex vertex = findMinVertex();
    Edge[] edges = findMinEdges();

    //Then, for each vertex and edges I found, I will change the color of 
    //them and pause the program for 3 seconds, so user can see how 
    //algorithm works.

    repaintAndPause(3000);
}
.
.
private void repaintAndPause(int time){
    long start = System.currentTimeMillis();
    long end = start + speed;

    //Here is the timer for repainting.
    Timer timer = new Timer(speed, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e){
            GraphPanel.this.repaint();
        }
    });
    timer.setRepeats(false);
    timer.setDelay(0);
    timer.start();

    //And here is for pausing the program, a while loop without any commands.
    while(System.currentTimeMillis() < end){}
}

但是,我不知道为什么,但程序不起作用。是的,有程序的暂停,但是所有的边和顶点都只是在程序结束时改变了颜色。它们不会每 3 秒更改一次。

谁能告诉我哪里做错了?

谢谢你,希望你有一个愉快的一天!

【问题讨论】:

    标签: java multithreading swing timer visualization


    【解决方案1】:

    谁能告诉我哪里做错了?

    是的。您在事件调度线程中放置了一个繁忙循环。

        while(System.currentTimeMillis() < end){}
    

    你的代码如下:

    1. 做一些计算(
    2. 完成后,发布“重绘”消息,以重绘面板不忙时
    3. 继续非常忙碌 3 秒内无所事事
    4. 通过重复步骤 1 到 4 继续忙碌

    while (condition) 循环最终完成之后,直到算法结束,事件调度线程才完成第一个“事件”的处理。

    你想要:

    Timer timer = new Timer(speed, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
           /* Code to perform one step of Prim's algorithm here */
           /* Change edge/vertex colour for step */
           /* Call timer.stop(), once done */
    
           GraphPanel.this.repaint();
        }
    });
    timer.setRepeats(true);
    timer.setDelay(3000);
    timer.start();
    

    在计时器的每一刻(每 3 秒一次),执行算法的一个步骤。

    请注意,这意味着算法的每一步都必须在运行时将任何部分结果存储到类成员中,因此下一步将能够检索到继续运行所需的所有信息。堆栈变量只能在一步内使用;它们不能用于保存跨步值。

    您可以修改算法以使用SwingWorker 在其自己的后台线程中运行计算,并在计算时使用publish 中间结果。然后,EDT 可以在生成中间结果时重新绘制。通过Thread#sleep() 调用,此后台线程可以将中间结果的生成延迟到每 3 秒一次。

    或者,您可以运行该算法,并为每个“步骤”存储多个输出副本。然后您的面板计时器可以简单地显示下一步的输出。

    【讨论】:

    • 感谢 AJNeufeld,您拯救了我的一天!它就像一个魅力!
    猜你喜欢
    • 2012-07-18
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 2022-11-02
    • 2018-07-27
    • 1970-01-01
    • 2012-07-04
    • 1970-01-01
    相关资源
    最近更新 更多