Jgraph http://www.jgraph.com/ 是一個(gè)開源的,兼容Swing的基于MVC體系結(jié)構(gòu)圖形組件,具有以下特點(diǎn):
1) 完全Swing兼容;
2) 簡單、高效的設(shè)計(jì);
3) 時(shí)間效率高;
4) 100 %純Java;
jGraph簡介
jGraph具有相當(dāng)高的交互性和自動(dòng)化,是一套為圖定做的組件。其主要用途是在一些需要表示圖結(jié)構(gòu)的應(yīng)用中,比如流程圖、UML、交通線路、網(wǎng)絡(luò)等等。
jGraph在本文撰寫時(shí)版本為5.8.0.0,可以在鏈接出找到j(luò)Graph的主頁。
jGraph主要包括以下一些產(chǎn)品:
JGraph - The Java Open Source Graph Drawing Component ( 有Open Source )
JGraph Layout Pro - The Java Graph Layout Solution
JGraphpad Pro Diagram Editor Framework
MxGraph Thin Client - JGraph in a browser!
咱們只是學(xué)習(xí)嘛,當(dāng)然只用jGraph咯。jGraph Layout Pro是一個(gè)對(duì)圖進(jìn)行布局的軟件,但是目前要收費(fèi)的,jGraph對(duì)圖的操作包括:圖顯示、圖交互、圖布局、圖分析等。
JGraph 的基本SWING 組件如下:
org.jgraph Basic JGraph 類
org.jgraph.event Graph 事件模型
org.jgraph.graph Graph 結(jié)構(gòu)及結(jié)點(diǎn)
org.jgraph.plaf Graph UI 委托組件
org.jgraph.util 常用的工具類
補(bǔ)充一下,與jGraph類似的可用于繪圖的還有eclipse的GEF。
jGraph模型
一張圖——JGraph 類 的主要結(jié)構(gòu):
JGraph extends JComponent {
org.jgraph.graph.GraphModel model; (DefaultGraphModel)
org.jgraph.plaf.GraphUI ui; (BasicGraphUI)
org.jgraph.graph.GraphLayoutCache cache;
}
JGraph 除了SWING的MVC結(jié)構(gòu),即引用了MODEL和UI外,他還保持著一個(gè)奇怪的應(yīng)用GraphLayoutCache。 GraphLayoutCache 可以被看作是MODEL的一個(gè)擴(kuò)展,它的作用是保證圖中各結(jié)點(diǎn)的狀態(tài)以及一些外觀等。因?yàn)閳D的復(fù)雜性,使用一個(gè)GraphLayoutCache 可以用來處理這些復(fù)雜問題。
配置JGraph可以使用一系列的set方法,有許多很有用的功能可以開關(guān)。
圖的邏輯結(jié)構(gòu)——GraphModel 類:
滿足MVC的要求,GraphModel保存著所有的圖中的對(duì)象,它的默認(rèn)實(shí)現(xiàn)DefaultGraphModel能夠滿足一般的需求。
GraphModel包含三個(gè)基本操作:insert() , edit() , remove() 。這些操作會(huì)起到與GraphLayoutCache相同的效果,但與GraphLayoutCache略微不同的是它的參數(shù)比較多,乍看下去比較麻煩。 其實(shí)GraphModel所要求的只是結(jié)點(diǎn)的邏輯結(jié)構(gòu),對(duì)于結(jié)點(diǎn)的細(xì)節(jié)它并不關(guān)心。所以可以在初始化圖時(shí)使用GraphModel,不要常常用它的方法來 對(duì)細(xì)節(jié)做修改,這既不方便,也沒必要。
另外,就是GraphModel提供了許多get方法,可以很方便檢索相應(yīng)的結(jié)點(diǎn)。
Cells
JGraph 的單位(Cells) 有三種:Vertex、 Edge、 Port。
Vertex 可以攜帶對(duì)象,由于JGraph是只負(fù)責(zé)表示的,并不真正負(fù)責(zé)數(shù)據(jù)的操作。那么在圖形和數(shù)據(jù)間就需要一個(gè)使者,這就是Vertex ,Vertex 可以是文字、圖形等對(duì)象。
Port 是一般比較陌生的單位,在圖的算法中并不設(shè)計(jì)Port,但在圖形表示中它十分有用。如同它的名字,他是Vertex上的一個(gè)端口,可以通過端口連接其他Vertex,而在JGraph中Port還可以用于改變Edge的形狀等等。
Edge 與圖算法中的邊也有一點(diǎn)不同,Edge 是只能連接Port而不是Vertex的。這樣,因?yàn)槎嗔薖ort單元,使得Edge更加靈活、更加豐富了。
默認(rèn)單元——DefaultCell:
它是DefaultEdge和DefaultPort的父類,又是DefaultMutableTreeNode的子類,其地位可以相當(dāng)于Vertex。 一個(gè)DefaultCell可以攜帶一個(gè)UserObject。每個(gè)DefaultCell還有一個(gè)AttributeMap,負(fù)責(zé)它的屬性(顏色、大小 等等)。用一套set方法可以修改AttributeMap。
邊和端口單元——Edge、Port:
除了繼承DefaultCell,Edge、Port還有一些獨(dú)有的方法。
Edge有g(shù)etSource() 和 getTarget() 方法,用以獲得邊的兩端的對(duì)象(一般為Port)。還一個(gè)路由類,定義了一些路由方法。
Port 主要任務(wù)是承載Edge,所以有一些關(guān)于獲得Edge的方法。另外,Port還定義了獲得錨(比如一個(gè)Vertex中包含一個(gè)Port)的方法。
Cell的處理:
每個(gè)Cell包括Cell Object、Cell Renderer、Cell Editor、Cell Handle。其中Renderer負(fù)責(zé)Cell的表示,包括形狀等等。Editor 做Cell的修改用,當(dāng)雙擊Cell后則調(diào)用Editor來編輯Cell。以上都是類似與JTable 和 JTree的。
Handle 是SWING的組件中沒有的,它的任務(wù)是處理Cell的大小與移動(dòng)。可以重寫paint()方法來指定經(jīng)過鼠標(biāo)拖動(dòng)所導(dǎo)致的Cell大小和位置變化。
對(duì)于這些單元的屬性的控制,可以仔細(xì)看看GraphConstants這個(gè)類的set方法,基本上所有的屬性都是用這個(gè)類的set修改的。
二、JGraph設(shè)計(jì)
1) MVC
Swing是Java(Sun)提供的UI標(biāo)準(zhǔn)實(shí)現(xiàn)之一,Swing基于AWT(Abstract Windowing Toolkit)。JGraph完全兼容Swing,它的實(shí)現(xiàn)仍然基于MVC體系結(jié)構(gòu)。
JGraph MVC
View:
JGraph不包含實(shí)際的數(shù)據(jù),它提供了數(shù)據(jù)的視;JGraph對(duì)象畫圖的機(jī)制是:
將圖元定義為一個(gè)一個(gè)的 cell,每個(gè)cell可以是一個(gè)頂點(diǎn)(vertex)、邊(edge)或者節(jié)點(diǎn)(port)中的一種。頂點(diǎn)可以有鄰接的頂點(diǎn),他們通過邊相聯(lián)系,邊聯(lián)接 的兩個(gè)端點(diǎn)稱為目標(biāo)和源,每個(gè)目標(biāo)或者源是一個(gè)節(jié)點(diǎn)。節(jié)點(diǎn)是頂點(diǎn)的孩子。每個(gè)cell都可以有自己的孩子。
每個(gè)cell的外觀由相應(yīng)的屬性定義,屬性序列是指一系列的鍵-值對(duì),他們以Map形式組織,例如:
Map cellAttrib = new Hashtable();
// Set bounds
Rectangle2D helloBounds = new Rectangle2D.Double(20, 20, 40, 20);
GraphConstants.setBounds(cellAttrib, helloBounds);
// Set black border
GraphConstants.setBorderColor(cellAttrib, Color.black);
一個(gè)cell有類似這樣一個(gè)cellAttrib的Map,來定義其外觀。
外觀可以指定諸如一條邊的箭頭樣式等屬性。
Model:
數(shù)據(jù)對(duì)象可以看成是JGraph中兩個(gè)獨(dú)立結(jié)構(gòu) 的鏈接點(diǎn):grahp結(jié)構(gòu)和group結(jié)構(gòu)。Graph結(jié)構(gòu)基于圖論中的頂點(diǎn)、邊定義。Group結(jié)構(gòu)是cell的composition結(jié)構(gòu)。 Graph結(jié)構(gòu)中g(shù)etSource()和getTarget()方法,獲得源和目標(biāo)節(jié)點(diǎn)。而在group中通過getChild(), getParent()來獲得cell的組成結(jié)構(gòu)。
2) 低層基于圖論邏輯
即:一個(gè)圖G包含一個(gè)非空的元 素集V(G)和一個(gè)E(G),其中,E(G)是V(G)中兩個(gè)無序元素組成的二元組。V(G)稱為圖G頂點(diǎn)的集合,如果任意集合V(G)中的頂點(diǎn)x/y, (x,y)在E(G)中,邊(x,y)可能以連接頂點(diǎn)x和y的邊(弧)所代表,X與y就被稱為鄰接的,否則x與y不鄰接。
三、JGraph的應(yīng)用
以下是一個(gè)基于JGraph的Helloworld的分析:
import省略
public class HelloWorld {
public static void main(String[] args) {
// Construct Model and Graph
GraphModel model = new DefaultGraphModel();
JGraph graph = new JGraph(model);
graph.setSelectNewCells(true);
// Create Nested Map (from Cells to Attributes)
// 此Map中記錄所有屬性,其中的鍵-值對(duì)是cell-cellAttribute
// 每個(gè)cellAttribute又是一個(gè)Map,其鍵-值對(duì)是具體一個(gè)cell的屬性-值
Map attributes = new Hashtable();
// 以下建立兩個(gè)頂點(diǎn)(cell)Hello和World,并分別設(shè)置他們的屬性Map
// Create Hello Vertex
DefaultGraphCell hello = new DefaultGraphCell("Hello");
// Create Hello Vertex Attributes
Map helloAttrib = new Hashtable();
attributes.put(hello, helloAttrib);
// Set bounds
Rectangle2D helloBounds = new Rectangle2D.Double(20, 20, 40, 20);
GraphConstants.setBounds(helloAttrib, helloBounds);
// Set black border
GraphConstants.setBorderColor(helloAttrib, Color.black);
// Add a Port
// 每個(gè)頂點(diǎn)為了與其他頂點(diǎn)相鄰接,必須添加節(jié)點(diǎn)(cell)
DefaultPort hp = new DefaultPort();
hello.add(hp);
// Create World Vertex
DefaultGraphCell world = new DefaultGraphCell("World");
// Create World Vertex Attributes
Map worldAttrib = new Hashtable();
attributes.put(world, worldAttrib);
// Set bounds
Rectangle2D worldBounds = new Rectangle2D.Double(140, 140, 40, 20);
GraphConstants.setBounds(worldAttrib , worldBounds);
// Set fill color
GraphConstants.setBackground(worldAttrib, Color.orange);
GraphConstants.setOpaque(worldAttrib, true);
// Set raised border
GraphConstants.setBorder(worldAttrib,
BorderFactory.createRaisedBevelBorder());
// Add a Port
DefaultPort wp = new DefaultPort();
world.add(wp);
// 建立聯(lián)接兩個(gè)頂點(diǎn)的邊
// Create Edge
DefaultEdge edge = new DefaultEdge();
// Create Edge Attributes
Map edgeAttrib = new Hashtable();
attributes.put(edge, edgeAttrib);
// Set Arrow
int arrow = GraphConstants.ARROW_CLASSIC;
GraphConstants.setLineEnd(edgeAttrib , arrow);
GraphConstants.setEndFill(edgeAttrib, true);
// Connect Edge
// 邊的兩個(gè)端點(diǎn)就是兩個(gè)頂點(diǎn)的child節(jié)點(diǎn)(port)
ConnectionSet cs = new ConnectionSet(edge, hp, wp);
Object[] cells = new Object[]{edge, hello, world};
// Insert into Model
// model構(gòu)件完成
model.insert(cells, attributes, cs, null, null);
// Show in Frame
JFrame frame = new JFrame();
frame.getContentPane().add(new JScrollPane(graph));
//frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
1) 完全Swing兼容;
2) 簡單、高效的設(shè)計(jì);
3) 時(shí)間效率高;
4) 100 %純Java;
jGraph簡介
jGraph具有相當(dāng)高的交互性和自動(dòng)化,是一套為圖定做的組件。其主要用途是在一些需要表示圖結(jié)構(gòu)的應(yīng)用中,比如流程圖、UML、交通線路、網(wǎng)絡(luò)等等。
jGraph在本文撰寫時(shí)版本為5.8.0.0,可以在鏈接出找到j(luò)Graph的主頁。
jGraph主要包括以下一些產(chǎn)品:
JGraph - The Java Open Source Graph Drawing Component ( 有Open Source )
JGraph Layout Pro - The Java Graph Layout Solution
JGraphpad Pro Diagram Editor Framework
MxGraph Thin Client - JGraph in a browser!
咱們只是學(xué)習(xí)嘛,當(dāng)然只用jGraph咯。jGraph Layout Pro是一個(gè)對(duì)圖進(jìn)行布局的軟件,但是目前要收費(fèi)的,jGraph對(duì)圖的操作包括:圖顯示、圖交互、圖布局、圖分析等。
JGraph 的基本SWING 組件如下:
org.jgraph Basic JGraph 類
org.jgraph.event Graph 事件模型
org.jgraph.graph Graph 結(jié)構(gòu)及結(jié)點(diǎn)
org.jgraph.plaf Graph UI 委托組件
org.jgraph.util 常用的工具類
補(bǔ)充一下,與jGraph類似的可用于繪圖的還有eclipse的GEF。
jGraph模型
一張圖——JGraph 類 的主要結(jié)構(gòu):
JGraph extends JComponent {
org.jgraph.graph.GraphModel model; (DefaultGraphModel)
org.jgraph.plaf.GraphUI ui; (BasicGraphUI)
org.jgraph.graph.GraphLayoutCache cache;
}
JGraph 除了SWING的MVC結(jié)構(gòu),即引用了MODEL和UI外,他還保持著一個(gè)奇怪的應(yīng)用GraphLayoutCache。 GraphLayoutCache 可以被看作是MODEL的一個(gè)擴(kuò)展,它的作用是保證圖中各結(jié)點(diǎn)的狀態(tài)以及一些外觀等。因?yàn)閳D的復(fù)雜性,使用一個(gè)GraphLayoutCache 可以用來處理這些復(fù)雜問題。
配置JGraph可以使用一系列的set方法,有許多很有用的功能可以開關(guān)。
圖的邏輯結(jié)構(gòu)——GraphModel 類:
滿足MVC的要求,GraphModel保存著所有的圖中的對(duì)象,它的默認(rèn)實(shí)現(xiàn)DefaultGraphModel能夠滿足一般的需求。
GraphModel包含三個(gè)基本操作:insert() , edit() , remove() 。這些操作會(huì)起到與GraphLayoutCache相同的效果,但與GraphLayoutCache略微不同的是它的參數(shù)比較多,乍看下去比較麻煩。 其實(shí)GraphModel所要求的只是結(jié)點(diǎn)的邏輯結(jié)構(gòu),對(duì)于結(jié)點(diǎn)的細(xì)節(jié)它并不關(guān)心。所以可以在初始化圖時(shí)使用GraphModel,不要常常用它的方法來 對(duì)細(xì)節(jié)做修改,這既不方便,也沒必要。
另外,就是GraphModel提供了許多get方法,可以很方便檢索相應(yīng)的結(jié)點(diǎn)。
Cells
JGraph 的單位(Cells) 有三種:Vertex、 Edge、 Port。
Vertex 可以攜帶對(duì)象,由于JGraph是只負(fù)責(zé)表示的,并不真正負(fù)責(zé)數(shù)據(jù)的操作。那么在圖形和數(shù)據(jù)間就需要一個(gè)使者,這就是Vertex ,Vertex 可以是文字、圖形等對(duì)象。
Port 是一般比較陌生的單位,在圖的算法中并不設(shè)計(jì)Port,但在圖形表示中它十分有用。如同它的名字,他是Vertex上的一個(gè)端口,可以通過端口連接其他Vertex,而在JGraph中Port還可以用于改變Edge的形狀等等。
Edge 與圖算法中的邊也有一點(diǎn)不同,Edge 是只能連接Port而不是Vertex的。這樣,因?yàn)槎嗔薖ort單元,使得Edge更加靈活、更加豐富了。
默認(rèn)單元——DefaultCell:
它是DefaultEdge和DefaultPort的父類,又是DefaultMutableTreeNode的子類,其地位可以相當(dāng)于Vertex。 一個(gè)DefaultCell可以攜帶一個(gè)UserObject。每個(gè)DefaultCell還有一個(gè)AttributeMap,負(fù)責(zé)它的屬性(顏色、大小 等等)。用一套set方法可以修改AttributeMap。
邊和端口單元——Edge、Port:
除了繼承DefaultCell,Edge、Port還有一些獨(dú)有的方法。
Edge有g(shù)etSource() 和 getTarget() 方法,用以獲得邊的兩端的對(duì)象(一般為Port)。還一個(gè)路由類,定義了一些路由方法。
Port 主要任務(wù)是承載Edge,所以有一些關(guān)于獲得Edge的方法。另外,Port還定義了獲得錨(比如一個(gè)Vertex中包含一個(gè)Port)的方法。
Cell的處理:
每個(gè)Cell包括Cell Object、Cell Renderer、Cell Editor、Cell Handle。其中Renderer負(fù)責(zé)Cell的表示,包括形狀等等。Editor 做Cell的修改用,當(dāng)雙擊Cell后則調(diào)用Editor來編輯Cell。以上都是類似與JTable 和 JTree的。
Handle 是SWING的組件中沒有的,它的任務(wù)是處理Cell的大小與移動(dòng)。可以重寫paint()方法來指定經(jīng)過鼠標(biāo)拖動(dòng)所導(dǎo)致的Cell大小和位置變化。
對(duì)于這些單元的屬性的控制,可以仔細(xì)看看GraphConstants這個(gè)類的set方法,基本上所有的屬性都是用這個(gè)類的set修改的。
二、JGraph設(shè)計(jì)
1) MVC
Swing是Java(Sun)提供的UI標(biāo)準(zhǔn)實(shí)現(xiàn)之一,Swing基于AWT(Abstract Windowing Toolkit)。JGraph完全兼容Swing,它的實(shí)現(xiàn)仍然基于MVC體系結(jié)構(gòu)。
JGraph MVC
View:
JGraph不包含實(shí)際的數(shù)據(jù),它提供了數(shù)據(jù)的視;JGraph對(duì)象畫圖的機(jī)制是:
將圖元定義為一個(gè)一個(gè)的 cell,每個(gè)cell可以是一個(gè)頂點(diǎn)(vertex)、邊(edge)或者節(jié)點(diǎn)(port)中的一種。頂點(diǎn)可以有鄰接的頂點(diǎn),他們通過邊相聯(lián)系,邊聯(lián)接 的兩個(gè)端點(diǎn)稱為目標(biāo)和源,每個(gè)目標(biāo)或者源是一個(gè)節(jié)點(diǎn)。節(jié)點(diǎn)是頂點(diǎn)的孩子。每個(gè)cell都可以有自己的孩子。
每個(gè)cell的外觀由相應(yīng)的屬性定義,屬性序列是指一系列的鍵-值對(duì),他們以Map形式組織,例如:
Map cellAttrib = new Hashtable();
// Set bounds
Rectangle2D helloBounds = new Rectangle2D.Double(20, 20, 40, 20);
GraphConstants.setBounds(cellAttrib, helloBounds);
// Set black border
GraphConstants.setBorderColor(cellAttrib, Color.black);
一個(gè)cell有類似這樣一個(gè)cellAttrib的Map,來定義其外觀。
外觀可以指定諸如一條邊的箭頭樣式等屬性。
Model:
數(shù)據(jù)對(duì)象可以看成是JGraph中兩個(gè)獨(dú)立結(jié)構(gòu) 的鏈接點(diǎn):grahp結(jié)構(gòu)和group結(jié)構(gòu)。Graph結(jié)構(gòu)基于圖論中的頂點(diǎn)、邊定義。Group結(jié)構(gòu)是cell的composition結(jié)構(gòu)。 Graph結(jié)構(gòu)中g(shù)etSource()和getTarget()方法,獲得源和目標(biāo)節(jié)點(diǎn)。而在group中通過getChild(), getParent()來獲得cell的組成結(jié)構(gòu)。
2) 低層基于圖論邏輯
即:一個(gè)圖G包含一個(gè)非空的元 素集V(G)和一個(gè)E(G),其中,E(G)是V(G)中兩個(gè)無序元素組成的二元組。V(G)稱為圖G頂點(diǎn)的集合,如果任意集合V(G)中的頂點(diǎn)x/y, (x,y)在E(G)中,邊(x,y)可能以連接頂點(diǎn)x和y的邊(弧)所代表,X與y就被稱為鄰接的,否則x與y不鄰接。
三、JGraph的應(yīng)用
以下是一個(gè)基于JGraph的Helloworld的分析: