prefuse是一個非常不錯的開源可視化項目,尤其是用在social network/complex network上,個人感覺要比jung好。不過可惜的是,prefuse的user manual還在建設中,並且google resource也少得可憐。好在開源提供了源碼,只好看源碼了,呵呵。
prefuse user manual上提供了一個簡單的例子,這個例子的資料來自一個符合GraphML標準的xml檔案(socialnet.xml),大致內容如下:
xml 代碼
<?xml version="1.0" encoding="UTF-8"?><br /><!-- An excerpt of an egocentric social network --><br /><graphml xmlns="http://graphml.graphdrawing.org/xmlns"><br /><graph edgedefault="undirected"></p><p><!-- data schema --><br /><key id="name" for="node" attr.name="name" attr.type="string"/><br /><key id="gender" for="node" attr.name="gender" attr.type="string"/></p><p><!-- nodes --><br /><node id="1"><br /> <data key="name">Jeff</data><br /> <data key="gender">M</data><br /> </node><br /><edge source="21" target="128"></edge><br /><edge source="21" target="129"></edge></p><p></graph><br /></graphml>
大致就是這個樣子,程式也比較簡單。但是不可能在想要可視化某個社群網路的時候,資料都來自xml,其實大部分還是來自資料庫的。prefuse支援從資料庫直接擷取資料。不過它的user manual上沒講。只好自己探索。
先建立一個在mysql上測試資料庫。一個代表節點,一個代表邊。
-- phpMyAdmin SQL Dump<br />-- version 2.11.10<br />-- http://www.phpmyadmin.net<br />--<br />-- 主機: localhost<br />-- 產生日期: 2010 年 07 月 06 日 03:24<br />-- 伺服器版本: 5.0.22<br />-- PHP 版本: 5.2.13</p><p>SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";</p><p>--<br />-- 資料庫: `test`<br />--</p><p>-- --------------------------------------------------------</p><p>--<br />-- 表的結構 `node`<br />--</p><p>CREATE TABLE IF NOT EXISTS `node` (<br /> `id` int(10) unsigned NOT NULL auto_increment,<br /> `name` varchar(45) NOT NULL,<br /> `gender` varchar(45) NOT NULL,<br /> PRIMARY KEY (`id`)<br />) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=8 ;</p><p>--<br />-- 匯出表中的資料 `node`<br />--</p><p>INSERT INTO `node` (`id`, `name`, `gender`) VALUES<br />(1, 'cuiran', 'boy'),<br />(2, 'aojuan', 'girl'),<br />(3, 'zhangsan', 'boy'),<br />(4, 'lisi', 'girl'),<br />(5, 'aomiao', 'girl'),<br />(6, 'aoqian', 'girl'),<br />(7, 'wangwu', 'boy');<br />
--<br />-- 表的結構 `edge`<br />--</p><p>CREATE TABLE IF NOT EXISTS `edge` (<br /> `id` int(10) unsigned NOT NULL auto_increment,<br /> `sid` int(10) unsigned NOT NULL,<br /> `tid` int(10) unsigned NOT NULL,<br /> PRIMARY KEY (`id`)<br />) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;</p><p>--<br />-- 匯出表中的資料 `edge`<br />--</p><p>INSERT INTO `edge` (`id`, `sid`, `tid`) VALUES<br />(3, 2, 1),<br />(4, 3, 1),<br />(5, 4, 1),<br />(6, 5, 2),<br />(7, 6, 2),<br />(8, 7, 1);<br />
接下來隨便在兩個表中插入幾條資料,需要注意的是edge表中,sid和tid一定要在node表中存在(即node表中有id與其對應),否則prefuse在讀取時會拋出異常。
接下來是程式了:
java 代碼package com.cayden.prefuse;</p><p>import javax.swing.JFrame;</p><p>import prefuse.Constants;<br />import prefuse.Display;<br />import prefuse.Visualization;<br />import prefuse.action.ActionList;<br />import prefuse.action.RepaintAction;<br />import prefuse.action.assignment.ColorAction;<br />import prefuse.action.assignment.DataColorAction;<br />import prefuse.action.layout.graph.ForceDirectedLayout;<br />import prefuse.activity.Activity;<br />import prefuse.controls.DragControl;<br />import prefuse.controls.NeighborHighlightControl;<br />import prefuse.controls.PanControl;<br />import prefuse.controls.ZoomControl;<br />import prefuse.data.Graph;<br />import prefuse.data.Table;<br />import prefuse.data.io.sql.ConnectionFactory;<br />import prefuse.data.io.sql.DatabaseDataSource;<br />import prefuse.render.DefaultRendererFactory;<br />import prefuse.render.LabelRenderer;<br />import prefuse.util.ColorLib;<br />import prefuse.visual.VisualItem;</p><p>public class TestMySql {<br /> public static final String driverName = "com.mysql.jdbc.Driver";<br /> public static final String dbURL = "jdbc:mysql://localhost:3306/test";<br /> public static final String userName = "root";<br /> public static final String userPwd = "root";<br />/**<br /> * @param args<br /> */<br />public static void main(String[] args) {<br />// TODO Auto-generated method stub<br /> DatabaseDataSource datasrc = null; </p><p> try {<br /> //get database connection<br /> datasrc = ConnectionFactory.getDatabaseConnection(<br /> driverName, dbURL, userName, userPwd); </p><p> //create a table of data<br /> Table nodes = datasrc.getData("select * from node");<br /> Table edges = datasrc.getData("select * from edge"); </p><p> Graph graph = new Graph(nodes, edges, false, "id", "sid", "tid"); </p><p> Visualization vis = new Visualization();<br /> vis.add("graph", graph); </p><p> LabelRenderer r = new LabelRenderer("name");<br /> r.setRoundedCorner(8, 8);<br /> vis.setRendererFactory(new DefaultRendererFactory(r)); </p><p> int[] palette = new int[] {<br /> ColorLib.rgb(255,180,180), ColorLib.rgb(190,190,255)<br /> }; </p><p> DataColorAction fill = new DataColorAction("graph.nodes", "gender",<br /> Constants.NOMINAL, VisualItem.FILLCOLOR, palette);<br /> ColorAction textColor = new ColorAction("graph.nodes",<br /> VisualItem.TEXTCOLOR, ColorLib.gray(0));<br /> ColorAction edgesColor = new ColorAction("graph.edges",<br /> VisualItem.STROKECOLOR, ColorLib.gray(200)); </p><p> ActionList color = new ActionList();<br /> color.add(fill);<br /> color.add(textColor);<br /> color.add(edgesColor); </p><p> ActionList layout = new ActionList(Activity.INFINITY);<br /> layout.add(new ForceDirectedLayout("graph"));<br /> layout.add(new RepaintAction()); </p><p> vis.putAction("color", color);<br /> vis.putAction("layout", layout); </p><p> Display d = new Display(vis);<br /> d.setSize(720, 500);<br /> d.addControlListener(new DragControl());<br /> d.addControlListener(new PanControl());<br /> d.addControlListener(new ZoomControl());<br /> d.addControlListener(new NeighborHighlightControl()); </p><p> JFrame frame = new JFrame("Prefuse");<br /> frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br /> frame.setSize(800, 600);<br /> frame.add(d);<br /> frame.setVisible(true); </p><p> vis.run("color");<br /> vis.run("layout");<br /> } catch (Exception e) {<br /> e.printStackTrace();<br /> } </p><p>}<br />}<br />運行後:
:http://vdisk.weibo.com/s/bVYuL
針對下面很多評論提到了是否支援中文
因為上面採用的是MySQL可能在 顯示的時候中文會亂碼,
需要在串連的url上加上字元集 utf-8我後來在SQL2005上測試 中文也可以顯示。附圖片: