漫谈可视化Prefuse(三)---Prefuse API数据结构阅读有感
前篇回顾:上篇《漫谈可视化Prefuse(二)---一分钟学会Prefuse》主要通过一个Prefuse的具体实例了解了构建一个Prefuse application的具体步骤。一个Prefuse Application需要经过数据导入(文本数据、数据库)->Prefuse数据结构接收数据->注册各种效果的Actions->渲染Renderer->交互展现Display的流程。
摸清了Prefuse那些看似眼花缭乱的框架结构,剩下的就是抽丝剥茧,顺藤摸瓜,结合Manual和API掀开Prefuse的神秘面纱。首先从Prefuse的数据结构开始:
1.prefuse.data:该包主要包含了接口:Node(点)、Edge(边)、Tuple(元组)
类:CascadedTable(级联表)、Graph(图)、Schema(模式)、SpanningTree(生成树)、Table(表)、Tree(树)。每个结构都有自己的属性和方法,下面列举了一些接口和类的主要成员:
Edge:
方法:Node getAdjacentNode(Node n)
返回给定节点的相邻节点集合
方法:Graph getGraph()
返回改变所在图形对象graph
方法:Node getSourceNode()/getTargetNode()
返回源节点、目标节点
方法:boolean isDirected()
判断有向图还是无向图 Node:
Graph getGraph()
返回节点所在的图形graph
int getInDegree()
返回节点入度个数
int getOutDegree()
返回节点出度个数
int getDegree()
返回节点度数
java.util.Iterator inEdges()
返回指向该节点的边的迭代器
java.util.Iterator outEdges()
返回从节点指出的边的迭代器
java.util.Iterator edges()
返回边的迭代器
java.util.Iterator inNeighbors()
返回所有链入该节点的迭代器
java.util.Iterator outNeighbors()
Get an iterator over all adjacent nodes connected to this node by an outgoing edge (i.e., all nodes "pointed" to by this one).
返回所有链出该节点的迭代器
java.util.Iterator neighbors()
返回所有近邻节点的迭代器 Node getParent()
返回父节点
Edge getParentEdge()
返回父边
int getDepth()
返回深度(根节点深度为0)
int getChildCount()
返回子节点个数
int getChildIndex(Node child)
返回节点索引值
Node getChild(int idx)
根据序号获得相应节点
Node getFirstChild()
获得第一个子节点
Node getLastChild()
获得最后一个子节点
Node getPreviousSibling()
得到上一个兄弟节点
Node getNextSibling()
得到下一个兄弟节点
java.util.Iterator children()
获得孩子节点的迭代器
java.util.Iterator childEdges()
获得子边集合的迭代器 Tuple:
Schema getSchema()
返回tuple数据概要
Table getTable()
返回tuple所在图表
int getRow()
返回tuple所在行数 Graph:
构造方法:
public Graph()创建一个空的无向图;
public Graph(boolean directed)true为有向,false为无向;
public Graph(Table nodes, Boolean directed)根据给定节点集合创建有向/无向图;
public Graph(Table nodes, boolean directed, java.lang.String nodeKey, java.lang.String sourceKey,java.lang.String targetKey)
nodeKey起到标示作用,如果为null,则默认使用row numbers(行号)
public Graph(Table nodes, Table edges,Boolean directed)
public Graph(Table nodes, Table edges, boolean directed, java.lang.String sourceKey, java.lang.String targetKey)
还有一些常用方法如添加删除节点或边等。 Schema:
Schema类是表示一个表格的列,其属性包括列名、数据类型、默认值。
其构造方法有:
Schema()
Schema(int ncols)
Schema(java.lang.String[] names, java.lang.Class[] types)
Schema(java.lang.String[] names, java.lang.Class[] types, java.lang.Object[] defaults)
主要方法有添加删除列,获取列名,锁定Schema对象等。 Table:
表格是由一系列行和列数组组成的,每一行即为一个数据记录,每一列是由指定数据域和数据类的数据组成。表格的数据可以直接通过使用行数和列名称进行访问。
表格的行可以插入和删除。
Table的构造方法:
Table()
Table(int nrows, int ncols)
protected Table(int nrows, int ncols, java.lang.Class tupleType)
其主要包含添加删除行或列 Tree:
构造方法如下:
Tree()
Tree(Table nodes, Table edges)
Tree(Table nodes, Table edges, java.lang.String sourceKey, java.lang.String targetKey)
Tree(Table nodes, Table edges, java.lang.String nodeKey, java.lang.String sourceKey, java.lang.String targetKey)
其方法主要有获取删除子节点、父节点、根节点
2.prefuse.data下还有一些包如:
prefuse.data.column
该包中主要介绍了列属性中可以有不同类型的列值,如BooleanColumn、DateColumn表示列中存储布尔类型和日期类型的值。列类的抽象基类是AbstractColumn。
prefuse.data.event
该包主要包含一些监听类,比如ColumnListener、ExpressionListener等分别表示针对不同对象的监听。
3.Prefuse还至于一些表达式的应用以及Prefuse对于各类表达式的解析
prefuse.data.expression(表达式)
该包主要包含了Prefuse关于表达式用法的类,有AndPredicate、NotPredicate、OrPredicate、ArithmeticExpression、BinaryExpression等分别表示AndPredicate(与)、OrPredicate(或)、NotPredicate(非)、ArithmeticExpression(算术表达式)、BinaryExpression(二进制表达式)等。
prefuse.data.expression.parser(表达式解析)
该包包含如何解析表达式Expression的类。
Prefuse支持的表达式涵盖很全面:
支持操作符运算、流程控制如:”x+y“(加运算)、"x^y"(平方运算)、”x>y“(比较运算)、”IF test THEN x ELSE
y“(if-then-else流程)等等;
一般常用函数如:"ISNODE()"(判断当前Tuple是否是一个节点)、”DEGREE()“(如果当前Tuple图中节点,返回该节点的度数)、”TREEDEPTH()“(如果当前Tuple是图中节点,则返回该节点在书中的深度)等;
数学运算如:"ABS(x)"(绝对值运算)、”SIN(x)“(正弦运算)、"FLOOR(x)"(向下取整)、”SUM(a,b,c...)“(求和运算)等等;
常用字符串运算如:”CAP(str)“(首字母大写)、”REPEAT(str,count)“(字符串替换操作)、”REVERSE(str)“(反转字符串)等等;
颜色控制函数如:”RGB(r,g,b)“(RGB模式颜色赋值)、”GRAY(v)“(灰度值模式颜色赋值)等;
综上相关表达式的支持,大大增强了Prefuse的灵活性,丰富了Prefuse的一些操作功能。
4.有关包prefuse.data.io以及prefuse.data.io.sql已经在《漫谈可视化Prefuse(一)---从SQL Server数据库读取数据》通过离子阐述过。
但是为了提高用户可操作性,也为了熟悉Java图形编程如何进行界面之间的传值,对上面文章中的例子进行了改进,将部分参数如端口号、数据库用户名、密码等信息开放给用户填写,提高程序的可操作性和灵活性,后期实际开发还会能够让用户在多中数据库之间切换。
我的界面传值思路:首先创建一个接收和读取数据的对象config,在填写参数的界面中画出文本框供用户填写参数,在完成按钮中添加监听事件,将所填信息赋给对象config,并执行在父界面中画出读取数据构成的图形,代码如下:
ConnectionToDB.java
public class ConnectionToDB{
public static Visualization vis = new Visualization();
public static Config config = new Config();//存储、获取参数对象
public static JFrame jf = new JFrame();
//标签显示
public static JLabel nodeLabel = new JLabel("节点查询:");
public static JLabel edgeLabel = new JLabel("边查询:");
public static JLabel strConfigLabel = new JLabel("配置字符串:");
public static JLabel databaseNameLabel = new JLabel("数据库名称:");
public static JLabel usernameLabel = new JLabel("用户名:");
public static JLabel passwordLabel = new JLabel("密码:");
public static JLabel portNumberLabel = new JLabel("端口号:"); //文本框
public static JTextField nodeText = new JTextField();
public static JTextField edgeText = new JTextField();
public static JTextField strConfigText = new JTextField();
public static JTextField databaseNameText = new JTextField();
public static JTextField usernameText = new JTextField();
public static JTextField passwordText = new JTextField();
public static JTextField portNumberText = new JTextField(); /**
* @param args
* @throws DataIOException
*/
public static void main(String[] args) throws DataIOException {
//1.构建显示画面 2.填写参数配置 3.配置传值到主界面 4.主界面图形展示 //-----------1、构建主界面-----------
JMenu dataMenu = new JMenu("数据导入");//添加菜单按钮
final JMenuItem dataItem = new JMenuItem("连接数据库");
dataItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
final JFrame second = new JFrame("second");
second.setSize(400,400);
second.setLayout(null);
strConfigLabel.setBounds(50, 20, 80, 30);
strConfigText.setBounds(130, 20, 150, 30);
second.add(strConfigLabel);
second.add(strConfigText); databaseNameLabel.setBounds(50, 60, 80, 30);
databaseNameText.setBounds(130, 60, 150, 30);
second.add(databaseNameLabel);
second.add(databaseNameText); usernameLabel.setBounds(50, 100, 80, 30);
usernameText.setBounds(130, 100, 150, 30);
second.add(usernameLabel);
second.add(usernameText); passwordLabel.setBounds(50, 140, 80, 30);
passwordText.setBounds(130, 140, 150, 30);
second.add(passwordLabel);
second.add(passwordText); portNumberLabel.setBounds(50, 180, 80, 30);
portNumberText.setBounds(130, 180, 150, 30);
second.add(portNumberLabel);
second.add(portNumberText); nodeLabel.setBounds(50, 220, 80, 30);
nodeText.setBounds(130, 220, 150, 30);
second.add(nodeLabel);
second.add(nodeText); edgeLabel.setBounds(50, 260, 80, 30);
edgeText.setBounds(130, 260, 150, 30);
second.add(edgeLabel);
second.add(edgeText); JButton ok = new JButton("完成配置");
ok.setBounds(70, 300, 100, 30);
second.add(ok);
second.setVisible(true);
ok.addActionListener(new ActionListener() { @Override
public void actionPerformed(ActionEvent e) {
if(nodeText.getText()!=null && edgeText.getText()!=null){
configPass();
System.out.println("node:"+ config.getNodeSql());
try {
actionEvent();
// second.dispose();这种关闭方式也可以
second.dispatchEvent(new WindowEvent(second,WindowEvent.WINDOW_CLOSING));//关闭子窗口
visual();
} catch (DataIOException e1) {
e1.printStackTrace();
}
}
}
}); } });
JMenuBar bar = new JMenuBar();
bar.add(dataMenu);
dataMenu.add(dataItem); jf.setSize(new Dimension(800, 600));
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setJMenuBar(bar);
// jf.pack();
jf.setVisible(true); } /**
* 存储配置界面用户输入的值
*/
private static void configPass() {
config.setNodeSql(nodeText.getText());
config.setEdgeSql(edgeText.getText());
config.setStrConfig(strConfigText.getText());
config.setDatabaseName(databaseNameText.getText());
config.setUsername(usernameText.getText());
config.setPassword(passwordText.getText());
config.setPortNumber(portNumberText.getText());
} /**
* 连接数据库并添加相应效果渲染和动作
* @throws DataIOException
*/
public static void actionEvent() throws DataIOException{ String driver = config.getStrConfig().toString();
String url = "jdbc:sqlserver://localhost:"+config.getPortNumber().toString()+";DatabaseName="+config.getDatabaseName().toString()+"";
String username = config.getUsername().toString();
String password = config.getPassword().toString();
DatabaseDataSource dbds = null;
try {
dbds = ConnectionFactory.getDatabaseConnection(driver, url, username, password);
} catch (SQLException e1) {
e1.printStackTrace();
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
System.out.println(config.getEdgeSql());
Table nodes = dbds.getData(config.getNodeSql().toString());
Table edges = dbds.getData(config.getEdgeSql().toString()); Graph graph = new Graph(nodes, edges, false, "id", "sid", "tid"); vis.add("graph", graph); LabelRenderer label = new LabelRenderer("name");
label.setRoundedCorner(10, 10); vis.setRendererFactory(new DefaultRendererFactory(label)); int[] palette = new int[]{ColorLib.rgb(255, 180, 180),ColorLib.rgb(190, 190, 255)};
DataColorAction fill = new DataColorAction("graph.nodes" , "gender" , Constants.NOMINAL, VisualItem.FILLCOLOR,palette);
ColorAction text = new ColorAction("graph.nodes", VisualItem.TEXTCOLOR, ColorLib.gray(0));
ColorAction edges1 = new ColorAction("graph.edges", VisualItem.STROKECOLOR, ColorLib.gray(200)); ActionList color = new ActionList();
color.add(fill);
color.add(text);
color.add(edges1); ActionList layout = new ActionList(Activity.INFINITY);
layout.add(new ForceDirectedLayout("graph"));
layout.add(new RepaintAction()); vis.putAction("color", color);
vis.putAction("layout", layout); } /**
* 添加控制器,显示图形
*/
public static void visual(){ Display display = new Display(vis);
display.setSize(700, 600);
display.pan(250, 250);
display.addControlListener(new DragControl());
display.addControlListener(new PanControl());
display.addControlListener(new ZoomControl());
display.addControlListener(new WheelZoomControl());
display.addControlListener(new FocusControl(1));
display.addControlListener(new ZoomToFitControl());
jf.add(display);
vis.run("color");
vis.run("layout");
} }
Config.java:
public class Config { public String nodeSql;
public String edgeSql;
public String strConfig;
public String databaseName;
public String username;
public String password;
public String portNumber; public String getStrConfig() {
return strConfig;
}
public void setStrConfig(String strConfig) {
this.strConfig = strConfig;
}
public String getDatabaseName() {
return databaseName;
}
public void setDatabaseName(String databaseName) {
this.databaseName = databaseName;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPortNumber() {
return portNumber;
}
public void setPortNumber(String portNumber) {
this.portNumber = portNumber;
}
public String getNodeSql() {
return nodeSql;
}
public void setNodeSql(String nodeSql) {
this.nodeSql = nodeSql;
}
public String getEdgeSql() {
return edgeSql;
}
public void setEdgeSql(String edgeSql) {
this.edgeSql = edgeSql;
} }
具体图形如下:
(1)带有功能菜单的父界面:
(2)参数配置界面:
(3)填写配置参数界面:
(4)图形显示在父界面并关闭配置窗口:
因为之前对于Swing和AWT编程不是很熟悉,考虑在界面传值也可以做,但是对于多个字符串的传值可能逻辑比较复杂,这里采用一个类Config用来封装数据从而完成数据的存储和读取的工作。
本文链接《漫谈可视化Prefuse(三)---Prefuse API数据结构阅读有感》
http://www.cnblogs.com/bigdataZJ/p/VisualizationPrefuse3.html
后续将继续API之路,了解Prefuse使用的套路,先顺着它,依着它,摸清它的脾性后再一举拿下它^_^
友情赞助
如果你觉得博主的文章对你那么一点小帮助,恰巧你又有想打赏博主的小冲动,那么事不宜迟,赶紧扫一扫,小额地赞助下,攒个奶粉钱,也是让博主有动力继续努力,写出更好的文章^^。
1. 支付宝 2. 微信
漫谈可视化Prefuse(三)---Prefuse API数据结构阅读有感的更多相关文章
- 漫谈可视化Prefuse(四)---被玩坏的Prefuse API
这个双12,别人都在抢红包.逛淘宝.上京东,我选择再续我的“漫谈可视化”系列(好了,不装了,其实是郎中羞涩...) 上篇<漫谈可视化Prefuse(三)---Prefuse API数据结构阅读有 ...
- 漫谈可视化Prefuse(五)---一款属于我自己的可视化工具
伴随着前期的基础积累,翻过API,读过一些Demo,总觉得自己已经摸透了Prefuse,小打小闹似乎已经无法满足内心膨胀的自己.还记得儿时看的<武状元苏乞儿>中降龙十八掌最后一张居然是空白 ...
- 漫谈可视化Prefuse(二)---一分钟学会Prefuse
前篇<漫谈可视化Prefuse(一)---从SQL Server数据库读取数据>主要介绍了prefuse如何连接数据库sql server并读取数据进行可视化展现. 回头想想还是应该好好捋 ...
- 漫谈可视化Prefuse(五)
伴随着前期的基础积累,翻过API,读过一些Demo,总觉得自己已经摸透了Prefuse,小打小闹似乎已经无法满足内心膨胀的自己.还记得儿时看的<武状元苏乞儿>中降龙十八掌最后一张居然是空白 ...
- 漫谈可视化Prefuse(六)---改动源码定制边粗细
可视化一路走来,体会很多:博客一路写来,收获颇丰:代码一路码来,思路越来越清晰.终究还是明白了一句古话:纸上得来终觉浅,绝知此事要躬行. 跌跌撞撞整合了个可视化小tool,零零碎碎结交了众多的志同道合 ...
- 漫谈可视化Prefuse(六)
可视化一路走来,体会很多:博客一路写来,收获颇丰:代码一路码来,思路越来越清晰.终究还是明白了一句古话:纸上得来终觉浅,绝知此事要躬行. 跌跌撞撞整合了个可视化小tool,零零碎碎结交了众多的志同道合 ...
- 35 网络相关函数(三)——live555源码阅读(四)网络
35 网络相关函数(三)——live555源码阅读(四)网络 35 网络相关函数(三)——live555源码阅读(四)网络 简介 5)NoReuse不重用地址类 6)initializeWinsock ...
- Vue.js 组件的三个 API:prop、event、slot
组件的构成 一个再复杂的组件,都是由三部分组成的:prop.event.slot,它们构成了 Vue.js 组件的 API.如果你开发的是一个通用组件,那一定要事先设计好这三部分,因为组件一旦发布,后 ...
- Navisworks 提供了.NET, COM和NwCreate 三种API
Navisworks 提供了.NET, COM和NwCreate 三种API.而通常我们说Navisworks API其实指的只是COM或.NET,因为NwCreate的功能比较特殊.待我一一道来: ...
随机推荐
- Windows下Oracle安装图解----oracle-win-64-11g 详细安装步骤
一. Oracle 下载 官方下地址 http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.htm ...
- Restful.Data 开源持久层组件项目最新进展和使用说明
Restful.Data 经过 博客园 和 CSDN 的宣传,目前参与该项目的人数已达到 114 人(群号:338570336),虽大部分并不参与实际开发,但他们所提出的意见和建议以及在试用过程中发现 ...
- Linux(CentOS 6.5)下配置Mono和Jexus并且部署ASP.NET MVC5
1.开篇说明 a. 首先我在写这篇博客之前,已经在自己本地配置了mono和jexus并且成功部署了asp.net mvc项目,我也是依赖于在网上查找的各种资料来配置环境并且部署项目的,而其在网上也已有 ...
- 可在广域网部署运行的QQ高仿版 -- GG2014 完美版!新增支持:聊天记录、好友分组、托盘闪动消息提醒、登录状态、GIF动态表情
距上次GG V3.7版本(可在广域网部署运行的QQ高仿版 -- GG叽叽V3.7,优化视频聊天.控制更多相关细节)的发布,已经有50天了,这50天对于GG来说,是一个重大的飞跃.因为这段时间通过一些基 ...
- 动态绑定HTML
在Web前端开发中,我们经常会遇见需要动态的将一些来自后端或者是动态拼接的HTML字符串绑定到页面DOM显示,特别是在内容管理系统(CMS:是Content Management System的缩写) ...
- 【开源】开发者新闻聚合APP 2.0.3发布(第二个稳定版本)
聚合了博客园新闻.infoq新闻.36kr新闻.oschina新闻.51cto新闻.csdn新闻: 争取做到随时刷随时有开发者的新闻! 目前还只支持安卓APP 但用的人多了,我会发布苹果版的APP 最 ...
- 认识SQLServer索引以及单列索引和多列索引的不同
一.索引的概念 索引的用途:我们对数据查询及处理速度已成为衡量应用系统成败的标准,而采用索引来加快数据处理速度通常是最普遍采用的优化方法. 索引是什么:数据库中的索引类似于一本书的目录,在一本书中使 ...
- java提高篇(十四)-----字符串
可以证明,字符串操作是计算机程序设计中最常见的行为. 一.String 首先我们要明确,String并不是基本数据类型,而是一个对象,并且是不可变的对象.查看源码就会发现String类为f ...
- GitHub初体验(小菜新手github用起来)
记得自己刚认识github的时候觉得他好高端,只知道好多牛人托管代码在上面,但是还觉得离我好遥远.其实不然,用起来,哇塞,真强大. 如果你现在像我当时一样茫然,那希望我的分享能帮助到你.(记录自己用起 ...
- knh
市场调研,分析—— 决定是否创业 不要再极度的沉默无言.宅.无存在感,无趣,难熬..