我昨天发布了一个问题,在这里使用scheduledexecutorservice What should I do in order to prevent the UI from freezing(scheduledexecutorservice)时防止用户界面冻结,大多数人建议使用SwingWorker而不是scheduledexecutorservice。但是,从那时起我就一直试图弄清楚SwingWorker线程在我的情况下是如何工作的。
我有以下伪代码:
createGraph(){
if(rule1)
n = new Node()
graph.add(n)
animateGraph()
createGraph()
if(rule2)
...
我有一个递归算法,它根据某些规则创建一个图形,我希望在匹配规则并将新的顶点/边添加到图形时更新UI。我的问题是,无论何时添加新节点/边缘,我如何显示图表?这应该发生在animateGraph()方法中,当它遇到这个方法时,它应该更新实际的UI,最好等待1500ms,直到整个图形构建完成。
我尝试创建一个SwingWorker线程。在这种情况下,它不显示图形创建的中间步骤,而只显示最终图形。首先,它执行对doInBackground()的所有调用,然后执行done()。
注意:每次创建新的顶点/边时,我都会创建一个新的SwingWorker线程,因为我读到doInBackground()只被调用一次。
private void animateGraph() {
swingWorker = createRunnable();
swingWorker.execute();
}
private void displayGraph() {
JPanel.add(graph);
}
private SwingWorker<Object, Object> createRunnable() {
swingWorker = new SwingWorker<Object, Object>() {
@Override
protected Void doInBackground() throws Exception {
System.out.println("Start sleeping.. " + new Date());
Thread.sleep(1500);
publish(new NodeTuple(new Node("A"), new Node("B")));
return null;
}
protected void process(List<NodeTuple> chunks) {
System.out.println("In process.. " + new Date());
NodeTuple nodeTuple = chunks.get(chunks.size() - 1);
graph.addVertex(nodeTuple.source);
graph.addVertex(nodeTuple.target);
checkIfToAddEdge(nodeTuple.source, nodeTuple.target);
createDiagram();
}
}
};
return swingWorker;
}
编辑:我更新了doInBackground()和process()方法。但是,我仍然没有得到我真正想要的东西。没有显示中间步骤,只显示最终图表。
答案 0 :(得分:1)
您应该使用publish
的{{1}} / process
API(请参阅代码的SwingWorker
API doc的第二个示例)。
这将允许您递归地创建节点并离开EDT,然后SwingWorker
匹配您的规则的新节点,然后在EDT上最终publish
这些节点进行显示或动画。
添加动画需要它自己的线程,我建议你将它添加为一个单独的任务,但至少你应该能够看到新的节点在添加到图形中时显示出来。
答案 1 :(得分:1)
要查看中间步骤,您必须publish()
创建每个新Node
,并在事件发送线程上process()
,就像它们在Tasks that Have Interim Results中所示。
class FlipTask extends SwingWorker<List<Node>, Node> {
@Override
protected List<Node> doInBackground() {
…
publish(new (Node);
…
}
protected void process(List<Node> list) {
// add each new Node to the view
}
}