使用计时器在固定时间内重新绘制,然后继续计算



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

这是我的程序输出的图像

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 秒更改一次。

有人可以告诉我我哪里做错了吗?

谢谢你,希望你有一个美好的一天!

有人可以告诉我我哪里做错了吗?

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

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 秒一次。

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

相关内容

最新更新