对于具有以下要求的网络图,可以使用哪些开源 Java 图形绘制框架?该图的节点数将少于 1000 个。

1)有平行边
2) 单个图中的有向边和无向边
3)图像表示的节点
4)用户与节点和边的交互
5)动态添加/删除节点和边
6)节点和边上的多重标记,用户可以关闭/打开不同级别的标记。(就像分层绘制和关闭/打开图层一样)
7) 不同的布局算法来显示星形、环形、网状拓扑

我评价了JUNG和Prefuse。这是我为我的每个要求找到的。

1) Prefuse 无法显示平行边,而 JUNG 支持。可以操纵 prefuse 代码来显示平行边缘吗?由于这涉及基本数据级别的更改,我相信这比通常的自定义渲染更改更困难。

2)我在 prefuse 和 JUNG 中都没有找到任何对组合图(有向边和无向边)的引用。还有人知道吗?

3) 对于 Prefuse 和 JUNG 来说这似乎很容易

4) 同样,prefuse 和 JUNG 都提供了对用户交互的支持。

5)prefuse和JUNG都支持。重绘图表时每个框架的表现如何?我在另一篇文章中看到 prefuse 对于动态更新表现不佳(预熔丝工具包:动态添加节点和边)

6) 这归结为修改图形并重新绘制它。所以问题就和5)一样了

7) JUNG和prefuse都有多种布局算法。但是当我尝试在 JUNG 和 Prefuse 中使用 FruchtermanReingoldLayout 显示相同的数据集时,我得到了不同的显示。有什么想法吗?不知何故,Prefuse 中的布局算法似乎比 JUNG 中显示更好的布局(我认为渲染也更好),尽管 Prefuse 中的大多数布局算法都基于 JUNG 实现。Prefuse 布局如 ForceDirectedLayout/FruchtermanReingoldLayout 和 CircleLayout 直接映射到星形、圆形、网状拓扑。

除了这些要求之外,prefuse 对表达式和查询语言有很好的支持,但看起来不像 JUNG 那样积极开发。哪一个的可视化效果更好?对于哪一种合适以及如何克服缺点有什么建议吗?

还有其他我可以使用的框架吗?

有帮助吗?

解决方案

几年前(2007 年?)我使用 prefuse 来可视化通话数据记录。我考虑了 prefuse、jung、jgraph 和其他一些,并选择了 prefuse。起初,我有点难以理解 prefuse,但一旦我熟悉了它,它就非常容易(扩展)并且使用起来很有趣。我想 JUNG 也可以这样说,但我从未尝试过。

1) 在 prefuse 中,很容易添加您自己的自定义渲染器来绘制平行边缘 - 您可以继承默认 EdgeRenderer 并重写 render() 方法。不需要“基本数据级别更改”。如果您想将其视为 MVC 内容,那么这一切都在视图部分中。

2)这根本不是一个问题。有不止一种方法可以做到这一点:1)您可以有两个渲染器 - 一个用于绘制有向边缘,另一个用于绘制无向边缘,它们会很好地工作,并对边缘进行适当的分组。2)放置一个标志(在 prefuse 中的支持表元组中添加一个布尔列)来指示边缘是否有向,并根据该标志在 EdgeRender 中相应地跳过箭头绘制部分。

3)这非常简单

4)同上

5) 最后一个 prefuse 版本是“prefuse beta 版本 2007.10.21”。我之前使用过一个,它在动态添加或删除节点时可能存在竞争条件 - 我猜它缺少一些同步关键字。我通过确保在添加或删除节点时停止所有动画和操作(颜色、大小、布局)来解决这个问题 - 也不要忘记更新你的 lucene 索引(如果你确实使用其内置的 lucene 搜索引擎) )。最新的应该可以解决这个比赛问题,但我从未有机会尝试。

6)既然你提到了“多重标签”,我认为这不是“修改图形并重新绘制它”的问题 - 这只是自定义标签/边缘渲染器以仅绘制相关标签的问题,所以这并不是一个大问题。而且我认为这与5根本没有关系。

7) 我并不惊讶 prefuse 和 JUNG 对 FruchtermanReingoldLayout 的渲染不同 - 有几个因素可能会影响其中一个因素,即每个实现开始计算的起始节点,所以我不会太担心这个问题。在 prefuse 中尝试不同的内置图形布局算法非常容易,因此您可以继续检查哪一个最接近您想要的算法。查看星形布局的 RadialLayout 和 BalloonTreeLayout。ForceDirectedLayout 需要相当多的迭代才能使节点的放置“稳定”。请注意,不必显示这些迭代,因此您可以在后台运行它并呈现最终结果。

我没有使用过JUNG,所以无法对它发表太多评论。

根据我使用 prefuse 的经验,我强烈推荐它,因为它经过深思熟虑的设计和组件之间的责任分离。杰弗里·希尔(Jeffrey Heer)(前言作者)确实做得很好。

使用 prefuse 时需要注意的事项(这是我在使用 prefuse 时清楚地记得的两个“痛点”):

1) 有一个错误,当缩小时,节点标签没有适当缩小,以致它溢出节点的边界框,这将在节点移动时留下字体绘制伪像,因为渲染器仅清除并重新绘制节点边界内的内容盒子。IIRC 这是由 AWT 字体度量本身的错误引起的。解决方法是在标签和节点边界框​​之间留出足够的边距。

2)扩展内置布局时,您可能会遇到一两个“范围问题”,其中您想要访问的超类成员被赋予私有属性而不是受保护,因此解决方案是修改库本身或创建一个新类而不继承(这可能有点痛苦!)。我想你也可以对其他一些 java 库说同样的话。不是每个人都能得到事后诸葛亮的好处不是吗?:)

自从您大约一个月前(在我撰写本文时)提出这个问题以来,我想知道您的决定是什么,以及如果您继续实施,结果如何。

其他提示

我是荣格的创造者和维护者之一,因此请记住以下回应。

不过,首先,我应该说,Prefuse的作者是朋友的朋友(是的,我们已经见面了),他做得很好。我没有经验丰富,但是我看到了一些与之创建的美丽可视化。

这是对荣格的问题的答案。其中几个((1),(2),(4)在 PluggableRendererDemo:

  1. 支持(您需要正确的数据模型,并非出于绩效原因所有支持平行边缘)
  2. 支持(同样,您需要正确的数据模型)
  3. 支持(见 ImageShaperDemo)
  4. 支持(大多数演示)
  5. 支持(见 GraphEditorDemo)
  6. 不直接支持,尽管您肯定可以动态更改标签并使用HTML呈现复杂标签。
  7. Jung的布局算法更多地用于通用网络(树木等有少数例外)。但是,您当然可以构建自己的布局算法,许多人这样做。

希望这可以帮助。

我知道您指定了Jung和Prefuse,但是...我在Tomsawyer和Yfiles都有很好的经验。您提出的需求列表非常基础,这是这两者的基础 - 它们支持更多。

跑。

我建议评估 Jgraph 也。

我喜欢 @holygeek的答案。这是我对2个解决方案的实现(指向和无方向的边缘),以预先使用:

public class MyRenderFactory implements RendererFactory
{
    private NodeRenderer nodeRenderer = new NodeRenderer();
    private EdgeRenderer defaultEdgeRenderer = new EdgeRenderer();
    private EdgeRenderer undirectedEdgeRenderer = new EdgeRenderer(EdgeRenderer.EdgeType.LINE, EdgeRenderer.EdgeArrowType.NONE);

    public static String directedness = "myEdgeDirectedness";

    public enum EdgeDirected
    {
        directed, undirected;

        public static EdgeDirected fromIsDirected(boolean isDirected)
        {
            if (isDirected)
            {
                return directed;
            }
            return undirected;
        }
    }

    @Override
    public Renderer getRenderer(VisualItem<?> visualItem)
    {
        if (visualItem instanceof EdgeItem)
        {
            if (visualItem.get(directedness).equals(PrefuseGraphConverter.EdgeDirected.undirected))
            {
                return undirectedEdgeRenderer;
            }
            return defaultEdgeRenderer;
        }
        return nodeRenderer;
    }
}

...在其他地方,创建图...

MyRenderFactory.EdgeDirected directedness =
        MyRenderFactory.EdgeDirected.fromIsDirected(myEdge.isDirected());
prefuseEdge.set(MyRenderFactory.directedness, directedness);
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top