Prefuse工具包:动态添加节点和边

4

你有使用prefuse图形工具包的经验吗?是否可以更改已显示的图形,例如添加/删除节点和/或边缘,并使显示正确适应?

例如,prefuse带有一个示例,可将朋友网络可视化:

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

我希望你能够做一些与此类似的事情:
// -- 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();

但似乎它不起作用。有什么提示吗?
4个回答

6

您需要了解Prefuse的几个层次:

  • 数据
  • 可视化
  • 显示

简而言之,这三个层次可以这样链接:

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

显示是一个通常添加到面板的图形组件。

在这里,您只修改数据层。

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

现在你需要更新可视化层:

viz.run("repaint");

必须定义repaint操作。

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

我强烈建议您阅读Prefuse文档。在官方论坛上,您还可以找到许多资源。
至少,我可以告诉你,目前来看,Prefuse对于实时图形更新并不是非常有效。
但这还不够,因为您修改了图形结构,所以必须在可视化中重新生成它(即重新计算节点位置等)。在您的示例代码中已经定义了两个动作。在actionPerformed的末尾运行它们。
viz.run("color");
viz.run("layout");

这种方法并不是很高效,因为每次添加节点时都会增加很多计算量,但目前在prefuse中没有其他方法。


非常感谢您的帮助。我已经阅读了文档,知道了三个不同的层次,但是我还没有尝试过重新绘制操作。不幸的是,它也不起作用。我已经将该操作添加到viz中,并在actionPerformed(如上所示)的末尾调用了viz.run(“repaint”),但没有效果。 - Thomas
请问您能否再看一下这个关于Prefuse库的问题:http://stackoverflow.com/questions/2273068/how-to-display-3-nodes-with-3-diff-shapes-in-prefuse-library-for-java - Amit

6
如我在另一篇文章中指出的那样,原始示例中新节点和边缘不可见的原因是节点的颜色等设置不正确。修复此问题的一种方法是在添加节点或边缘时显式调用vis.run("color")。
另一种方法是通过略微不同地初始化ActionList(在原始示例中称为“color”)来确保颜色操作始终运行:
而不是
ActionList color = new ActionList();

我们可以编写

ActionList color = new ActionList(Activity.INFINITY);

这将使动作列表无限运行,以便为其视觉外观自动初始化新的节点/边缘。

然而,我不确定这实际上是否是首选方法 - 对于像动态布局操作(例如ForceDirectedLayout)这样的东西,这样的声明是完全合理的,但对于颜色,似乎不断运行着色操作大部分都是额外开销。

因此,也许之前发布的解决方案只在图形扩展时显式地运行“color”操作(但仅运行一次)可能是更好的选择...


请问您能否看一下这个网址上的另一个Prefuse相关问题:http://stackoverflow.com/questions/2273068/how-to-display-3-nodes-with-3-diff-shapes-in-prefuse-library-for-java。谢谢! - Amit

2

好的,在查阅了一些prefuse源代码后,我对内部运作方式有了更好的理解。我发现实际上我用上面的代码创建的新节点不仅被正确地添加到了图形中,可视化也注意到了它!

因此,与Jerome的建议不同,没有必要显式调用vis.run("layout")。

我认为节点未被正确添加的原因是它们被绘制为带有白色背景、边框和文本颜色 - 在白色背景上。难怪它们有点难以发现。

要解决这个问题,需要在插入新节点后调用颜色动作,像这样:

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

(请注意,此操作在Example.jar代码中的//-- 4.)部分有进一步定义。)

最后一个我现在不确定的事情是调用此操作是否会使Prefuse再次遍历所有图形节点并设置它们的颜色——对于非常大的图形来说,这将是不期望的。


请您能否看一下这个关于Prefuse库的问题:http://stackoverflow.com/questions/2273068/how-to-display-3-nodes-with-3-diff-shapes-in-prefuse-library-for-java - Amit

0

非常感谢您的提示 - 我尝试了一下,但不起作用。我认为节点没有实现为AWT或Swing组件,prefuse使用自己的机制进行布局。这可能是它不关心invalidate()调用的原因。 - Thomas
不,它仍然是Swing/AWT内部的。查看Javadocs有关损坏管理的信息。此外,repaint和revalidade也可能起作用。如果有疑问,请阅读Java教程。 - aldrinleal
请问您能否再看一下这个关于Prefuse库的问题:http://stackoverflow.com/questions/2273068/how-to-display-3-nodes-with-3-diff-shapes-in-prefuse-library-for-java - Amit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接