I have a question that involves GraphStream within a Swing GUI. I know that is slightly out of scope of GraphStream per se, but my investigations led to a final question that I think is relevant.
I followed the tutorial in integrating a GraphStream viewer in a Swing GUI (http://graphstream-project.org/doc/Tutorials/Graph-Visualisation_1.1/#integrating-the-viewer-in-your-gui) and everything was ok. My problem was later getting a ConcurrentModificationException while trying to modify a graph in response to a Swing event.
My goal is to be able to handle Swing events (buttons, etc.) to dynamically update a GraphStream graph (modify styles, etc.). I wrote a small test of that. Here is an excerpt:
/* =============================== */
import java.util.Collection;
import org.graphstream.graph.Node;
import org.graphstream.ui.graphicGraph.GraphicGraph;
import org.graphstream.ui.swingViewer.Viewer;
public class ToggleGreen {
javax.swing.JToggleButton button;
public javax.swing.JToggleButton getButton() {return button;}
public void setButton(javax.swing.JToggleButton button) {this.button = button;}
private static GraphicGraph graph = null;
public GraphicGraph getGraph() {return graph;}
public void setGraph(GraphicGraph _graph) {graph = _graph;}
ToggleGreen(Viewer networkViewer) {
setGraph(networkViewer.getGraphicGraph());
button = new javax.swing.JToggleButton("Green", false);
button.addItemListener (new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent event) {
if (button.isSelected()) {
System.out.println("Green ON");
/* This throws
* Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
* at java.util.HashMap$HashIterator.nextEntry(Unknown Source)
* at java.util.HashMap$KeyIterator.next(Unknown Source)
* at org.graphstream.ui.graphicGraph.StyleGroupSet$ElementIterator.next(StyleGroupSet.java:1419)
* at org.graphstream.ui.graphicGraph.StyleGroupSet$ElementIterator.next(StyleGroupSet.java:1403)
* at ToggleGreen$1.itemStateChanged(ToggleGreen.java:33) */
for (Node node: getGraph().getEachNode()) {
node.addAttribute("ui.style", "fill-color:green;");
}
/* This throws
* Exception in thread "AWT-EventQueue-0" java.lang.RuntimeException: not implemented !
* at org.graphstream.ui.graphicGraph.GraphicGraph.getNode(GraphicGraph.java:1223)
* at ToggleGreen$1.itemStateChanged(ToggleGreen.java:42) */
//Collection<Node> nodeSet = getGraph().getNodeSet();
//for (int i = 0; i < nodeSet.size(); i++) {
// Node node = getGraph().getNode(i);
// node.addAttribute("ui.style", "fill-color:green;");
//}
}
}
});
}
}
/* =============================== */
This class creates a JToggleButton, which I added to my GUI, along with a GraphStream viewer. The instatiated viewer is passed into this class, giving a handle to the graph in the viewer. The button event then attempts to add a green color to each graph node.
With the code above, this throws the concurrent modification exception (after painting a single node green). I am somewhat new to Swing, but I see that this is a well-known problem with iterating over Java Collections within threads. I tried various suggestions such as synchronized(), but was never successful in eliminating the concurrent modification exception. As a sanity check, I tested that
for (Node node: getGraph().getEachNode()) {
node.addAttribute("ui.style", "fill-color:green;");
}
works fine outside of the Swing thread.
Another suggestion I saw was to reference the list/array using its index rather than an iterator, which is commented out in the code example. That is this:
for (int i = 0; i < nodeSet.size(); i++) {
Node node = getGraph().getNode(i);
node.addAttribute("ui.style", "fill-color:green;");
}
For this, I get "java.lang.RuntimeException: not implemented !" Presumably this is coming from a GraphStream try/catch, indicating that the getNode() method is not yet implemented?
Thanks in advance for any suggestions.
Regards,
Steve
Archives gérées par MHonArc 2.6.16.