jGraphX 绘图总结,增加大量节点和边的效率问题。

来源:互联网 发布:滑窗的方法 数据分析 编辑:程序博客网 时间:2024/06/04 00:53

参考jGraphx手册:
http://jgraph.github.io/mxgraph/docs/manual_javavis.html#1.6.1
JGraphX的核心是JGraphX Model
几乎所有的修改动作,都需要调用model的方法:


下面是核心方法:

  • mxGraphModel.beginUpdate() - starts a new transaction or a sub-transaction.
  • mxGraphModel.endUpdate() - completes a transaction or a sub-transaction.
  • mxGraph.addVertex() - Adds a new vertex to the specified parent cell.
  • mxGraph.addEdge() - Adds a new edge to the specified parent cell.
  • mxGraph.insertVertex(parent, id, value, x, y, width, height, style) – creates and inserts a new vertex into the model, within a begin/end update call.
  • mxGraph.insertEdge(parent, id, value, source, target, style) – creates and inserts a new edge into the model, within a begin/end update call.
Model change 方法:
  • add(parent, child, index)
  • remove(cell)
  • setCollapsed(cell, collapsed)
  • setGeometry(cell, geometry)
  • setRoot(root)
  • setStyle(cell, style)
  • setTerminal(cell, terminal, isSource)
  • setTerminals(edge,source,target)
  • setValue(cell, value)
  • setVisible(cell, visible)
在使用上述方法的时候一般的时候需要用

mxGraphModel.beginUpdate() 和mxGraphModel.endUpdate() 进行包围,对所做的改动进行更新。

如果没有使用上述函数进行包围,在修改的时候,系统也会更新。如:insertEdge,insertVertex等函数。

如库代码所示,这两个函数都会调用addCells。 在这里会调用beginUpdate和endUpdate对增加后的graph范围进行更新。

public Object[] addCells(Object[] cells, Object parent, Integer index,Object source, Object target){if (parent == null){parent = getDefaultParent();}if (index == null){index = model.getChildCount(parent);}model.beginUpdate();try{cellsAdded(cells, parent, index, source, target, false, true);fireEvent(new mxEventObject(mxEvent.ADD_CELLS, "cells", cells,"parent", parent, "index", index, "source", source,"target", target));}finally{model.endUpdate();}return cells;}

但是强烈建议不要使用这种默认方式进行更新。用户要显示的调用更新。

因为默认方式更新会对大量节点和边的graph会产生性能上的问题。

如在项目中遇到需要在图中增加19万条边。在使用insertEdge增加边的时候,开始的时候很快,但是后来会越来越慢。

增加边耗时完全不是线性的,而是指数的。 19万条边需要6个小时才增加完成。如下代码:

for (int i = 0; i < pVectorLines.size(); i++) {            VectorLine vl = pVectorLines.get(i);            Object s = vGraphObjectMap.get(vl.getStartPos());            Object e = vGraphObjectMap.get(vl.getEndPos());            Object edge = graph.insertEdge(parent, null, "", s, e, edgeStyle);        }

而采取自己显示增加边的方法,只需不到20秒就可以完成。

方法是将for循环用beginUpdate和endUpdate进行包围。

其默认方式导致性能上的问题。其原因是在于endUpdate函数,因为每次增加一个边,都会调用

beginUpdate和endUpdate. 而且更新范围会随着边的增加而增加,从而导致耗时越来越长。


我们可以看到库中的源代码。这里有个updateLevel,如果以前调用过beginUpdate,在addCells函数中就不会进行更新。

public void beginUpdate(){updateLevel++;fireEvent(new mxEventObject(mxEvent.BEGIN_UPDATE));}public void endUpdate(){updateLevel--;if (!endingUpdate){endingUpdate = updateLevel == 0;fireEvent(new mxEventObject(mxEvent.END_UPDATE, "edit", currentEdit));try{if (endingUpdate && !currentEdit.isEmpty()){fireEvent(new mxEventObject(mxEvent.BEFORE_UNDO, "edit",currentEdit));mxUndoableEdit tmp = currentEdit;currentEdit = createUndoableEdit();tmp.dispatch();fireEvent(new mxEventObject(mxEvent.UNDO, "edit", tmp));}}finally{endingUpdate = false;}}}


0 0
原创粉丝点击