Reputation: 51
I posted a question yesterday about preventing the UI from freezing when using a scheduledexecutorservice here What should I do in order to prevent the UI from freezing(scheduledexecutorservice) and most people suggested using SwingWorker instead of scheduledexecutorservice. However, I've been stuck since then trying to figure out how a SwingWorker thread would work in my case.
I have the following pseudocode:
createGraph(){
if(rule1)
n = new Node()
graph.add(n)
animateGraph()
createGraph()
if(rule2)
...
I have a recursive algorithm which creates a graph based on certain rules and I want to update the UI when a rule is matched and a new vertex/edge is added to the graph. My question is how can I display the graph whenever a new node/edge is added to it? This should happen in the animateGraph() method and when it hits this method, it should update the actual UI, preferably wait for 1500ms and do that until the whole graph is built.
I tried creating a SwingWorker thread. In this case it doesn't show the intermediate steps of the graph creation but only the final graph. First, it executes all calls to doInBackground() and then it goes to done().
NB: I create a new SwingWorker thread every time a new vertex/edge is created as I read that doInBackground() is only called once.
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;
}
Edit: I updated doInBackground() and process() methods. However, I still don't get what I really want. No intermediate steps are shown and only the final graph is displayed.
Upvotes: 0
Views: 1079
Reputation: 7126
To see the intermediate steps, you have to publish()
each new Node
as it's created and process()
it on the event dispatch thread, like they show in 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
}
}
Upvotes: 1
Reputation: 27054
You should probably use the publish
/process
API of the SwingWorker
(see the second example of the SwingWorker
API doc for code).
This will allow you create nodes recursively and off the EDT, then publish
new nodes matching your rule, before finally process
ing these nodes on the EDT for display or animation.
Adding animation will need it's own thread, and I suggest you add that as a separate task, but at least you should be able to see new nodes showing up as they are added to the graph.
Upvotes: 1