漫谈可视化Prefuse(四)---被玩坏的Prefuse API

  这个双12,别人都在抢红包、逛淘宝、上京东,我选择再续我的“漫谈可视化”系列(好了,不装了,其实是郎中羞涩。。。)

  上篇《漫谈可视化Prefuse(三)---Prefuse API数据结构阅读有感》主要介绍了可视化工具Prefuse API中主要解读的是prefuse.data包中的主要接口,并利用《漫谈可视化Prefuse(一)---从SQL Server数据库读取数据》中例子,将参数配置模块剥离出来,实现界面传值,绘制图形。

  本篇决定不再贴API,实在没啥意思,还占篇幅(但是不容置疑的是API确实很重要,想了解API点这里)。那今天我们主要讲讲Prefuse比较常用的包以及如何使用这些包做出自己想要的展示效果:

  Demo1.解决图形元素形状单一化问题——DataShapeAction的使用

  

  Prefuse对于节点的形状默认是使用Constants.SHAPE_RECTANGLE,这里使用DataShapeAction类完成一个图形中根据性别不同展示不同的节点形状,具体代码如下:

 1 public class Demo1 {
 2
 3     /**
 4      * @param args
 5      */
 6     public static void main(String[] args) {
 7
 8         Graph graph = null;
 9         try {
10             graph = new GraphMLReader().readGraph("socialnet.xml");
11         } catch (Exception e) {
12             e.printStackTrace();
13             System.out.println("Error loading");
14             System.exit(1);
15         }
16
17         Visualization vis = new Visualization();
18         vis.add("graph", graph);
19         vis.setRendererFactory(new DefaultRendererFactory());
20
21         int[] palette = new int[]{ColorLib.rgb(255, 180, 180),ColorLib.rgb(190, 190, 255)};
22         DataColorAction fill = new DataColorAction("graph.nodes" , "gender" , Constants.NOMINAL, VisualItem.FILLCOLOR,palette);
23         ColorAction text = new ColorAction("graph.nodes", VisualItem.TEXTCOLOR, ColorLib.gray(0));
24         ColorAction edges = new ColorAction("graph.edges", VisualItem.STROKECOLOR, ColorLib.gray(200));
25
26         int[] shapes = new int[]{ Constants.SHAPE_RECTANGLE, Constants.SHAPE_DIAMOND};
27         DataShapeAction shape = new DataShapeAction("graph.nodes", "gender", shapes);
28
29         ActionList color = new ActionList();
30         color.add(fill);
31         color.add(text);
32         color.add(edges);
33         color.add(shape);
34
35         ActionList layout = new ActionList(Activity.INFINITY);
36         layout.add(new ForceDirectedLayout("graph"));
37         layout.add(new RepaintAction());
38
39         vis.putAction("color", color);
40         vis.putAction("layout", layout);
41
42         Display display = new Display(vis);
43         display.setSize(750, 700);
44         display.pan(250, 250);
45         display.addControlListener(new DragControl());
46         display.addControlListener(new PanControl());
47         display.addControlListener(new ZoomControl());
48         display.addControlListener(new WheelZoomControl());
49         display.addControlListener(new FocusControl(1));
50         display.addControlListener(new ZoomToFitControl());
51
52         JFrame jf = new JFrame();
53         jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
54         jf.add(display);
55         jf.pack();
56         jf.setVisible(true);
57
58         vis.run("color");
59         vis.run("layout");
60
61     }
62
63 }

  

  DataShapeAction中的第一个参数为指定数据范围,这里指定针对“graph.nodes”点集;第二个参数为属性域,这里针对性别不同赋予不同的形状;第三个参数是形状数组,这里定义了Constants.SHAPE_RECTANGLE, Constants.SHAPE_DIAMOND,除此之外还有Constants.SHAPE_CROSS、Constants.SHAPE_ELLIPSE、Constants.SHAPE_STAR等。同理prefuse.action.assignment包下的DataColorAction用法与DataShapeAction类似。图形展示效果如下:

  Demo2:打破输入输出流的垄断亲自绘制图形——Graph的使用

  之前几篇介绍的例子主要依赖于prefuse.io中的读入写出操作类进行数据的导入,这里我们决定甩开膀子,自己丰衣足食,打造自己的图形,这里主要使用Graph类的添加节点以及添加边的方法,构建一个互连的三个三角形的形状。具体代码如下:

 1 public class Demo2{
 2
 3     public static void main(String[] argv) {
 4         Visualization vis = new Visualization();
 5         Graph g = new Graph();
 6         for(int i = 0; i<3; i++){
 7             Node n1 = g.addNode();
 8             Node n2 = g.addNode();
 9             Node n3 = g.addNode();
10             g.addEdge(n1, n2);
11             g.addEdge(n2, n3);
12             g.addEdge(n3, n1);
13         }
14         g.addEdge(0, 3);
15         g.addEdge(3, 6);
16         g.addEdge(6, 0);
17
18         vis.add("graph", g);
19         ShapeRenderer renderer = new ShapeRenderer(10);
20         vis.setRendererFactory(new DefaultRendererFactory(renderer));
21
22         ColorAction nodeFill = new ColorAction("graph.nodes", VisualItem.FILLCOLOR, ColorLib.rgb(10, 150, 220));
23         ColorAction edgesStroke = new ColorAction("graph.edges", VisualItem.STROKECOLOR, ColorLib.rgb(100, 80, 180));
24         ColorAction nodeHighlight = new ColorAction("graph.nodes", VisualItem.HIGHLIGHT, ColorLib.rgb(10, 150, 220));
25
26         ActionList color = new ActionList();
27         color.add(nodeFill);
28         color.add(edgesStroke);
29
30         ActionList layout = new ActionList(Activity.INFINITY);
31         layout.add(color);
32         layout.add(new ForceDirectedLayout("graph"));
33         layout.add(new RepaintAction());
34
35         Display display = new Display(vis);
36         display.setSize(400, 500);
37         display.pan(250, 250);
38         display.addControlListener(new DragControl());
39         display.addControlListener(new PanControl());
40         display.addControlListener(new ZoomControl());
41         display.addControlListener(new WheelZoomControl());
42         display.addControlListener(new FocusControl(1));
43         display.addControlListener(new ZoomToFitControl());
44
45         vis.putAction("color", color);
46         vis.putAction("layout", layout);
47
48
49         JFrame frame = new JFrame();
50         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
51         frame.pack();
52         frame.setSize(600, 700);
53         frame.add(display);
54         frame.setVisible(true);
55
56         vis.run("color");
57         vis.run("layout");
58     }
59
60 } 

  从代码可以看出,对于创建节点、添加边,Graph处理的游刃有余,只有你想不到的图形,没有创建不了的Graph。当然只是简单创建了node和edge只是有了骨架,还需要血肉的填充,所以可以看到有很多的Action纷纷来助阵,最终的众志成城之作如下:

  Demo3:谁说点点之间只能“直肠子”——EdgeRenderer的使用

  看不惯点与点之间的“直肠子”?可以,Prefuse了解你,知道你喜新厌旧,这不使用EdgeRenderer就可以实现曲线连接,具体代码与Demo1相近,只是多了一下几行代码:

1 DefaultRendererFactory rf = new DefaultRendererFactory(label);
2 EdgeRenderer edgeRenderer = new EdgeRenderer(Constants.EDGE_TYPE_CURVE);
3 rf.add(new InGroupPredicate("graph.edges"), edgeRenderer);

  这里采用EdgeRenderer边渲染器,将边渲染为曲线,并统一应用到组“graph.edges”中的元素上,除了Constants.EDGE_TYPE_CURVE,还有Constants.EDGE_ARROW_FORWARD、Constants.EDGE_ARROW_NONE等。话不多说,看效果:

Demo4:Prefuse没节操?不知道筛选?No!——Predicate的使用

Prefuse自带过滤器,可以完成十分强大的过滤操作,视个别情况个别对待。拿Demo2中的图形来说,处在中间的节点可以不收节点控制(无法拖拽,不能交互),人家兄弟姐妹多,就拿那些势力若的边缘小弟拖过来拽过去^_^。具体代码如下:

 1 public class Demo4{
 2
 3     public static void main(String[] argv) {
 4         Visualization vis = new Visualization();
 5         Graph g = new Graph();
 6         for(int i = 0; i<3; i++){
 7             Node n1 = g.addNode();
 8             Node n2 = g.addNode();
 9             Node n3 = g.addNode();
10             g.addEdge(n1, n2);
11             g.addEdge(n2, n3);
12             g.addEdge(n3, n1);
13         }
14         g.addEdge(0, 3);
15         g.addEdge(3, 6);
16         g.addEdge(6, 0);
17         vis.add("graph", g);
18
19         ShapeRenderer renderer = new ShapeRenderer(10);
20         EdgeRenderer edgeRenderer = new EdgeRenderer(Constants.EDGE_TYPE_CURVE);
21         DefaultRendererFactory drf = new DefaultRendererFactory();
22         drf.add(new InGroupPredicate("graph.edges"), edgeRenderer);
23         vis.setRendererFactory(drf);
24
25         ColorAction nodeFill = new ColorAction("graph.nodes", VisualItem.FILLCOLOR, ColorLib.rgb(10, 150, 220));
26         ColorAction edgesStroke = new ColorAction("graph.edges", VisualItem.STROKECOLOR, ColorLib.rgb(100, 80, 180));
27         ColorAction nodeHighlight = new ColorAction("graph.nodes", VisualItem.HIGHLIGHT, ColorLib.rgb(10, 150, 220));
28
29         ShapeAction  shape = new ShapeAction("graph.nodes",Constants.SHAPE_CROSS); //设置节点形状
30
31         ActionList color = new ActionList();
32         color.add(nodeFill);
33         color.add(edgesStroke);
34         color.add(shape);
35
36         ActionList layout = new ActionList(Activity.INFINITY);
37         layout.add(color);
38         layout.add(new ForceDirectedLayout("graph"));
39         layout.add(new RepaintAction());
40
41         Point p = new Point(100,200);
42         p.move(300, 400);
43
44
45         Predicate pCount =(Predicate)ExpressionParser.parse("degree()>2");
46
47         Display display = new Display(vis);
48         display.setSize(400, 500);
49         display.pan(250, 250);
50         display.animatePanAbs(230, 220, 2000);
51         display.addControlListener(new DragControl());
52         display.addControlListener(new PanControl());
53         display.addControlListener(new ZoomControl());
54         display.addControlListener(new WheelZoomControl());
55         display.addControlListener(new FocusControl(1));
56         display.addControlListener(new ZoomToFitControl());
57
58         vis.removeGroup("graph");
59         VisualGraph vg = vis.addGraph("graph", g);
60         Iterator nodes = vg.nodes();
61         display.addControlListener(new ControlAdapter() {
62             public void itemEntered(VisualItem item, MouseEvent e) {
63                 System.out.println("伦家已经是:" + item.getGroup()+"的人了");
64             }
65             public void itemExited(VisualItem item, MouseEvent e) {
66                 System.out.println("哦,那杰哥再找找-_-");
67             }
68         });//为组件添加监控并作相应的响应
69
70         vis.setInteractive("graph.nodes", pCount, false);
71
72         vis.putAction("color", color);
73         vis.putAction("layout", layout);
74
75
76         JFrame frame = new JFrame();
77         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
78         frame.pack();
79         frame.setSize(600, 700);
80         frame.add(display);
81         frame.setVisible(true);
82
83         vis.run("color");
84         vis.run("layout");
85     }
86
87 } 

  这里Predicate pCount =(Predicate)ExpressionParser.parse("degree()>2")表示过滤出节点度数大于2的,该过滤条件在vis.setInteractive("graph.nodes", pCount, false)中执行,即在组“graph.nodes”元素中节点度数大于2的不能交互(即鼠标拖拽无效)。

  另外从代码中可以看出当鼠标经过和离开VisualItem(点或边)时会执行相应的操作,下图展现了部分结果:

  Demo5:个性化定制,我有我个性——VisualItem的领悟

  要知道,在数据中心Visualizaiton里,每一个node或是edge都可以看成一个VisualItem,每个VisualItem都可以有属于自己的造型、尺寸,这里我们还是用Demo2中的图形继续玩,直到玩坏为止。具体代码如下:

 1 public class Demo5{
 2     public static Visualization vis = new Visualization();
 3
 4     public static void main(String[] argv) {
 5
 6         Graph g = new Graph();
 7         for(int i = 0; i<3; i++){
 8             Node n1 = g.addNode();
 9             Node n2 = g.addNode();
10             Node n3 = g.addNode();
11             g.addEdge(n1, n2);
12             g.addEdge(n2, n3);
13             g.addEdge(n3, n1);
14         }
15         g.addEdge(0, 3);
16         g.addEdge(3, 6);
17         g.addEdge(6, 0);
18
19         vis.add("graph", g);
20         ShapeRenderer renderer = new ShapeRenderer(10);
21         vis.setRendererFactory(new DefaultRendererFactory(renderer));
22
23         vis.removeGroup("graph");
24         VisualGraph vg = vis.addGraph("graph", g);
25         VisualItem nodeI = (VisualItem)vg.getEdge(7).getSourceNode();
26         nodeI.setShape(Constants.SHAPE_STAR);
27         nodeI.setSize(4);
28         nodeI.setFixed(true);
29         VisualItem edgeI = (VisualItem)vg.getEdge(5);
30         edgeI.setSize(8);
31
32         ColorAction nodeFill = new ColorAction("graph.nodes", VisualItem.FILLCOLOR, ColorLib.rgb(10, 150, 220));
33         ColorAction edgesStroke = new ColorAction("graph.edges", VisualItem.STROKECOLOR, ColorLib.rgb(100, 80, 180));
34         ColorAction nodeHighlight = new ColorAction("graph.nodes", VisualItem.HIGHLIGHT, ColorLib.rgb(10, 150, 220));
35
36         ActionList color = new ActionList();
37         color.add(nodeFill);
38         color.add(edgesStroke);
39
40         ActionList layout = new ActionList(3000);
41         layout.add(color);
42         layout.add(new ForceDirectedLayout("graph"));
43         layout.add(new RepaintAction());
44
45         Display display = new Display(vis);
46         display.setSize(400, 500);
47         display.pan(250, 250);
48         display.addControlListener(new DragControl());
49         display.addControlListener(new PanControl());
50         display.addControlListener(new ZoomControl());
51         display.addControlListener(new WheelZoomControl());
52         display.addControlListener(new FocusControl(1));
53         display.addControlListener(new ZoomToFitControl());
54         display.addControlListener(new ControlAdapter(){
55             public void itemEntered(VisualItem item, MouseEvent e) {
56
57                 System.out.println("伦家已经是:" + item.getGroup()+"的人了");
58                 vis.run("color");
59                 vis.run("layout");//重绘三秒
60             }
61         });
62
63         vis.putAction("color", color);
64         vis.putAction("layout", layout);
65
66
67         JFrame frame = new JFrame();
68         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
69         frame.pack();
70         frame.setSize(600, 700);
71         frame.add(display);
72         frame.setVisible(true);
73
74         vis.run("color");
75         vis.run("layout");
76     }
77
78 } 

  可以看出代码中nodeI.setShape(Constants.SHAPE_STAR);nodeI.setSize(4);nodeI.setFixed(true);是将节点的形状设为星形,大小放大为4并固定此节点;edgeI.setSize(8);将边的粗细设为8。这里还具有一个功能,就是代码跑起来显示图形运行三秒,当鼠标经过某点或边是,整个图形在运行三秒,为展示这种效果,首次使用ps做gif,想想也是醉了。。。

  Prefuse就先玩到这吧,真材实料送上5个Demo,虽然抢不到红包,抢点Demo补补脑也不错哦,走到这里,似乎我已经拉近了与Prefuse的距离,下一步就是力求亲密接触,碰撞出可视化狂拽炫酷的展示效果。觉得有用,记得点赞哦。

本文链接:漫谈可视化Prefuse(四)---被玩坏的Prefuse APIhttp://www.cnblogs.com/bigdataZJ/p/VisualizationPrefuse4.html

时间: 2024-10-01 15:31:14

漫谈可视化Prefuse(四)---被玩坏的Prefuse API的相关文章

漫谈可视化Prefuse(五)

伴随着前期的基础积累,翻过API,读过一些Demo,总觉得自己已经摸透了Prefuse,小打小闹似乎已经无法满足内心膨胀的自己.还记得儿时看的<武状元苏乞儿>中降龙十八掌最后一张居然是空白页,在千钧一发之际以为自己要嗝屁了,一阵东风让苏乞儿明白了,最后一章要做的原来是--整合.没错,今天我们就来好好谈谈整合! 看懂API不代表你会灵活运用某个类,会用一些类不代表能实现小功能,耍的了小功能不一定会做可视化工具整合,整合之道,奥妙无穷! 前篇回顾:上篇<漫谈可视化Prefuse(四)---被

漫谈可视化Prefuse(五)---一款属于我自己的可视化工具

伴随着前期的基础积累,翻过API,读过一些Demo,总觉得自己已经摸透了Prefuse,小打小闹似乎已经无法满足内心膨胀的自己.还记得儿时看的<武状元苏乞儿>中降龙十八掌最后一张居然是空白页,在千钧一发之际以为自己要嗝屁了,一阵东风让苏乞儿明白了,最后一章要做的原来是——整合.没错,今天我们就来好好谈谈整合! 看懂API不代表你会灵活运用某个类,会用一些类不代表能实现小功能,耍的了小功能不一定会做可视化工具整合,整合之道,奥妙无穷! 前篇回顾:上篇<漫谈可视化Prefuse(四)---被

漫谈可视化Prefuse(二)---一分钟学会Prefuse

前篇<漫谈可视化Prefuse(一)---从SQL Server数据库读取数据>主要介绍了prefuse如何连接数据库sql server并读取数据进行可视化展现. 回头想想还是应该好好捋一捋prefuse框架中各个主要接口的职责以及如何有序使用它们构建一个prefuse应用.首先看图: 从图中可以发现一个prefuse程序的编写需要经历以下步骤: 准备好原始数据(文件或是数据库数据): 通过prefuse.data.io以及prefuse.data.io.sql包将数据读入prefuse,实

漫谈可视化Prefuse(六)---改动源码定制边粗细

可视化一路走来,体会很多:博客一路写来,收获颇丰:代码一路码来,思路越来越清晰.终究还是明白了一句古话:纸上得来终觉浅,绝知此事要躬行. 跌跌撞撞整合了个可视化小tool,零零碎碎结交了众多的志同道合之人,迷迷糊糊创建了我"可视化/Prefuse"的QQ群,详情可查看左侧的公告部分.此群旨在结实更多的可视化领域的同仁,也希望可以成为一个开源项目分享与阅读的平台.源于开源,开源为我们提供了助我们快速成长的养分,开源的每一行代码都是前辈们心血的结晶,开源是智慧的浓缩. 在博客园写博客也是如

漫谈可视化Prefuse(三)---Prefuse API数据结构阅读有感

前篇回顾:上篇<漫谈可视化Prefuse(二)---一分钟学会Prefuse>主要通过一个Prefuse的具体实例了解了构建一个Prefuse application的具体步骤.一个Prefuse Application需要经过数据导入(文本数据.数据库)->Prefuse数据结构接收数据->注册各种效果的Actions->渲染Renderer->交互展现Display的流程. 摸清了Prefuse那些看似眼花缭乱的框架结构,剩下的就是抽丝剥茧,顺藤摸瓜,结合Manua

那些年被我玩坏的点子和创意-下篇

时光如白驹过隙,继那些年被我玩坏的点子和创意-上篇已过一个月,平常忙活着和队友一起做产品了,挤得时间总结了下篇,分四个故事来说 自动发微博软件为啥做这个呢,淘宝客接口还没有限制以前好多玩淘宝客的.其中我发现有个淘宝客玩的挺特别的,他是在新浪微博和腾讯微博(当时还没有关闭),上通过时光机等一些定时发微博的平台给粉丝推送淘客商品信息,我还记得他的微博马甲叫"型男服装搭配",他推送的微博都是从淘宝男装男鞋等类目下的按销量等某些筛选条件后的top N条商品,我不知道这样效果怎么样,但我知道可以

[转]被玩坏的innerHTML、innerText、textContent和value属性

一.前言 由于innerText并非W3C标准属性,因此我们无法在FireFox中使用它,一般情况下我们可以使用textContent来代替,但它两者是否就能完全等同呢?在坑爹的表单元素(如input.textarea等)中表现是否依旧诡异呢?文本将记录一些实验结果,避免日后被玩坏. 二.innerHTML 由于innerText和textContent均为对innerHTML内容作不同的处理而成,因此我们需要先明确innerHTML属性的特点. 赋值操作:先对值内容进行模式匹配,然后把处理后的

JS魔法堂:被玩坏的innerHTML、innerText、textContent和value属性

一.前言 由于innerText并非W3C标准属性,因此我们无法在FireFox中使用它,一般情况下我们可以使用textContent来代替,但它两者是否就能完全等同呢?在坑爹的表单元素(如input.textarea等)中表现是否依旧诡异呢?文本将记录一些实验结果,避免日后被玩坏. 二.innerHTML 由于innerText和textContent均为对innerHTML内容作不同的处理而成,因此我们需要先明确innerHTML属性的特点. 赋值操作:先对值内容进行模式匹配,然后把处理后的

【读后感】读《漫谈“大学生的四个learn”》之后有感

在看完<许纪霖教授在上海财经大学演讲--漫谈"大学生的四个Learn">(下问简称<四l>)之后突然有点话想说.其实我对这篇文章有感的,所以想写这篇文章来说说看,我对四个learn的理解,以及对大学生的理解. 我在的学校名叫"福州大学至诚学院"(Fuzhou university Zhicheng college)严格来说并不算上"university"而是"college"(也就是大学下面所属的学院)