简体   繁体   English

Prefuse Toolkit:动态添加节点和边缘

[英]Prefuse Toolkit: dynamically adding nodes and edges

Does anyone have experience with the prefuse graph toolkit? 有没有人有prefuse图形工具包的经验? Is it possible to change an already displayed graph, ie. 是否可以更改已显示的图形,即。 add/remove nodes and/or edges, and have the display correctly adapt? 添加/删除节点和/或边缘,并使显示正确适应?

For instance, prefuse comes with an example that visualizes a network of friends: 例如,prefuse附带了一个可视化朋友网络的示例:

http://prefuse.org/doc/manual/introduction/example/Example.java http://prefuse.org/doc/manual/introduction/example/Example.java

What I would like to do is something along the lines of this: 我想做的是这样的事情:

// -- 7. add new nodes on the fly -------------------------------------
new Timer(2000, new ActionListener() {
    private Node oldNode = graph.nodes().next(); // init with random node

    public void actionPerformed(ActionEvent e) {
        // insert new node //
        Node newNode = graph.addNode();

        // insert new edge //
        graph.addEdge(oldNode, newNode);

        // remember node for next call //
        oldNode = newNode;
    }
}).start();

But it doesn't seem to work. 但它似乎没有用。 Any hints? 任何提示?

You should be aware the several layers of prefuse: 你应该知道几层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 . 我真的建议你阅读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. 至少,我可以说,prefuse目前对于实时图形更新并不是非常有效。

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. 在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"); 解决这个问题的一种方法是明确调用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: 或者,我们可以通过初始化我们添加它的ActionList(在原始示例中称为“color”)稍微不同来确保颜色操作始终在运行:

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 (eg ForceDirectedLayout), such a declaration makes perfect sense, but for colors it seems to me that a constantly running coloring action is mostly overhead. 然而,我不清楚这是否真的是首选的方法 - 对于像动态布局动作(例如ForceDirectedLayout)这样的事情,这样的声明非常有意义,但对于颜色来说,在我看来,持续运行的着色操作主要是高架。

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. 因此,与杰罗姆建议的不同,没有必要明确地调用vis.run(“布局”)。

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.) (请注意,此操作在// 4.下的Example.jar代码中进一步定义。)

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. 我现在最不确定的一件事是,调用此动作是否会使prefuse再次遍历所有图形节点并设置它们的颜色 - 当然,对于非常大的图形来说是不希望的。

You need to tell the control container ('d', in example.java) do get redrawn. 你需要告诉控件容器('d',在example.java中)重新绘制。 Calling invalidate() should be enough (not sure, though). 调用invalidate()应该足够了(但不确定)。

Anyway, this might help you. 无论如何,这可能会对你有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM