哪个开源Java图形绘制框架用于具有以下要求的网络图?该图表的节点少于1000个。
1)具有平行边缘
2)单个图形内的有向和无向边缘
3)由图像表示的节点
4)用户与节点和边缘的交互
5)动态添加/删除节点和边缘
6)节点和边缘上的多个标签,用户可以关闭/打开不同的标签级别。 (比如在图层中绘图并关闭/打开图层)
7)不同的布局算法,以显示星形,环形,网状拓扑
我评估了JUNG和Prefuse。这是我为每个要求找到的。
1)当JUNG支持时,Prefuse无法显示平行边缘。可以预操作代码来显示平行边缘吗?由于这涉及基本的数据级别更改,我相信通常的自定义渲染更改会更加困难。
2)我没有在prefuse和JUNG中找到对组合图(有向和无向边)的任何引用。有没有人知道呢?
3)这对Prefuse和JUNG来说似乎很容易
4)同样,prefuse和JUNG都为用户交互提供支持。
5)prefuse和JUNG都支持它。重绘图表时每个框架如何执行?我在另一篇文章中看到,prefuse在动态更新方面表现不佳( Prefuse Toolkit: dynamically adding nodes and edges)
6)这归结为修改图形并重新绘制它。所以问题就像5)
一样7)JUNG和prefuse都有多种布局算法。但是当我尝试在JUNG和Prefuse中使用FruchtermanReingoldLayout显示相同的数据集时,我会得到不同的显示。有什么想法吗?虽然Prefuse中的大多数布局算法都是基于JUNG实现的,Prefuse中的布局算法似乎显示出比JUNG更好的布局(渲染也更好)。 PreFuse布局(如ForceDirectedLayout / FruchtermanReingoldLayout和CircleLayout)直接映射到星形,圆形,网格拓扑。
除了这些要求之外,prefuse对表达式和查询语言有很好的支持,但看起来它并不像JUNG那样积极开发。哪一个有更好的可视化?关于哪一个适合以及如何克服缺点的任何建议?
我可以使用其他任何框架吗?
答案 0 :(得分:5)
我是JUNG的创作者和维护者之一,所以请记住下面的回答。
首先,我应该说Prefuse的作者是朋友的朋友(是的,我们见过面)并且他做得很好。我对Prefuse没有经验,但我已经看到了用它创建的一些漂亮的可视化。
以下是JUNG对这些问题的回答。其中几个((1),(2),(4)在PluggableRendererDemo
:
ImageShaperDemo
)GraphEditorDemo
)希望这有帮助。
答案 1 :(得分:3)
几年前(2007年?)我使用prefuse来显示呼叫数据记录。我考虑了prefuse,jung,jgraph和其他一些人,并选择了prefuse。起初有点难以将我的头包裹起来,但是一旦我熟悉它,它就非常容易(扩展)和使用起来很有趣。我想JUNG可以这么说,但我从未尝试过。
1)在prefuse中,添加自己的自定义渲染器以绘制平行边缘非常容易 - 您可以继承默认的EdgeRenderer并覆盖render()方法。不需要“基本数据级别更改”。如果您想将其视为MVC内容,那么这一切都在视图中。
2)这根本不是问题。有多种方法可以做到这一点:1)你可以有两个渲染器 - 一个用于绘制有向边,一个用于绘制无向边,它们可以正常工作,并适当地对边进行分组。 2)放置一个标志(在prefuse speak中的后备表元组中添加一个布尔列)以指示边缘是否被定向并根据该标志在EdgeRender中相应地跳过箭头绘制部分。
3)这非常容易
4)同上
5)最后一个prefuse版本是“prefuse beta release 2007.10.21”。我之前使用的那个,在动态添加或删除节点时可能存在竞争条件 - 我猜错了一些同步关键字。我通过确保在添加或删除节点时停止所有动画和操作(颜色,大小,布局)来解决这个问题 - 也不要忘记更新你的lucene索引(如果你使用它内置的lucene搜索引擎)。最新的一个应该解决这个种族问题,但我从来没有机会尝试过。
6)既然你提到了“多重标签”,我认为这不是“修改图形并重新绘制”的问题 - 只需要自定义标签/边缘渲染器来仅绘制相关标签,这样就不是真的了一个大问题。我也不认为这与5完全相关。
7)我并不感到惊讶,因为prefuse和JUNG对FruchtermanReingoldLayout的渲染是不同的 - 有一些因素可能会影响其中一个因素,即每个实现开始计算的起始节点,所以我不会太担心这个问题。在prefuse中尝试不同的内置图形布局算法非常容易,因此您可以继续检查哪一个最接近您想要的内容。查看RadialLayout和BalloonTreeLayout的星形布局。 ForceDirectedLayout需要相当多的迭代才能使节点的位置“稳定”。请注意,这些迭代不必显示,因此您可以在后台运行它并呈现最终结果。
我没有使用JUNG所以我不能对此发表评论。
根据我对prefuse的经验,我强烈推荐它,因为非常好(IMHO)深思熟虑的设计和组件之间的可靠性分离。杰弗里·希尔(prefuse作者)在那里做得很好。
如果你使用prefuse需要注意的事项(这些是我在使用prefuse时生动地记住的两个“痛苦的拇指”):
1)有一个错误,当缩小时,节点标签没有被适当地缩小,使得它溢出节点的边界框,当节点移动时会留下字体绘制工件,因为渲染器只清除并重绘内容节点的边界框。 IIRC这是由AWT字体指标本身的错误引起的。解决方法是在标签和节点边界框之间留出足够的边距。
2)扩展内置布局时,您可能会遇到一个或两个“范围问题”,其中您要访问的超类成员被赋予私有属性而不是受保护,因此解决方案是修改库本身或创建一个没有继承的新类(这可能有点痛苦!)。我想你可以对其他一些java库说同样的话。不是每个人都有后见之明的好处吗? :)
自从你在一个月前(在我写这篇文章时)提出这个问题以来,我想知道你的决定是什么,以及如果你继续实施它的结果。
答案 2 :(得分:2)
我知道你指定了jung和prefuse但是...... 我对TomSawyer和yFiles都有很好的经验。您提出的要求清单对于这两个要求非常基础 - 而且它们支持更多。
冉。
答案 3 :(得分:0)
我建议也评估JGraph。
答案 4 :(得分:0)
我喜欢@ holygeek的回答。以下是我对2的解决方案(有向和无向边)的实现,对于Prefuse:
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);