目前,我正在为查找最小生成树的图形可视化Prim算法制作Java程序。
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秒钟更换一次。
有人可以告诉我哪里做错了吗?
谢谢你,希望你过得愉快!
答案 0 :(得分:1)
有人可以告诉我哪里做错了吗?
是。您正在Event Dispatching Thread中放置一个忙循环。
while(System.currentTimeMillis() < end){}
您的代码为:
在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秒一次。
或者,您可以运行算法,并为每个“步骤”存储一次输出的多个副本。然后你的Panel计时器可以简单地显示下一步的输出。