Prefuse Toolkit: dynamically adding nodes and edges

百般思念 提交于 2019-11-29 23:24:05
Jérôme

You should be aware the several layers of prefuse:

  • Data
  • Visualization
  • Display

To be short, the three layers can be linked this way:

Graph graph = new Graph(eg. yourXML_file);
Visualization viz = new Visualization();
viz.add(GRAPH, graph);
Display disp = new Display();
disp.setVisualization(viz);

Display is a graphic component that you add to a panel as usual.

Here you only modify the data layer.

Node newNode = graph.addNode();
graph.addEdge(oldNode, newNode);

You need now to update the visual layer:

viz.run("repaint");

The repaint action has to be defined.

ActionList repaint = new ActionList();
repaint.add(new RepaintAction());
viz.putAction("repaint", repaint);

I really advise you to read the prefuse doc. And you can find a lot a resources on the official forum

At least, I can say you that prefuse is for the moment not really efficient for live graph update.

But it should not be enough, as you modified the graph structure, you have to regenerate it in the visualization (ie. recalculate the node placements etc...). There are two actions already defined in your sample code. Run them at the end of your actionPerformed.

viz.run("color");
viz.run("layout");

This method is not very efficient, because it adds a lot of computation each time you add a node, but there are not any others for the moment with prefuse.

As pointed out in my other post, the reason new nodes and edges are not visible in the original example is that the colors etc. for the nodes are not set correctly. One way to fix this is to explicitly call vis.run("color"); whenever a node or edge was added.

Alternatively, we can ensure that the color action is always running, by initializing the ActionList to which we add it (called "color" in the original example) slightly differently:

instead of

ActionList color = new ActionList();

we could write

ActionList color = new ActionList(Activity.INFINITY);

This keeps the action list running indefinitely, so that new nodes/edges will automatically be initialized for their visual appearance.

However, it is unclear to me whether this would actually be the preferred method - for things like a dynamic layout action (e.g. ForceDirectedLayout), such a declaration makes perfect sense, but for colors it seems to me that a constantly running coloring action is mostly overhead.

So, perhaps the previously posted solution of just running the "color" action explicitly (but only once) whenever the graph gets extended, might be the better choice...

Okay, after digging a bit through the prefuse sources, I now have a better understanding of how things work under the hood. I found out that actually the new nodes I create with the code above are not only added correctly to the graph, the visualization also takes note of it!

So, unlike Jerome suggests, it is not necessary to call vis.run("layout") explicitly.

The reason I thought the nodes were not added correctly was the fact that they are drawn with white background-, border- and text color - on white background that is. Not astonishing that they are a bit difficult to spot.

To fix that one has to call the color action after a new node is inserted, like this:

// insert new edge //
graph.addEdge(oldNode, newNode);
vis.run("color"); // <- this is new

(Note that this action is defined further up in the code of Example.jar under //-- 4.)

One last thing I am unsure about now is whether calling this action will make prefuse go over all graph nodes again and set their color - for very large graphs that would be undesired, of course.

You need to tell the control container ('d', in example.java) do get redrawn. Calling invalidate() should be enough (not sure, though).

Anyway, this might help you.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!