StupidBeauty
Read times:2779Posted at:Mon Nov 26 05:01:47 2012
- no title specified

Prefuse文档翻译:介绍 > 示例程序,introduction > example application

在这一小节中,我们会分析 一个prefuse 程序示例: 一个简单的社交网络可视化。 我们的可视化程序会 将一个社交网络呈现出来 ,展现出一个根据力学规则控制 其布局的动画效果,节点 会按照性别来分配 不同颜色,并且 会显示出它们所代表的人的名字。 以下代码都是写在一个程序 main 方法里的。 此示例的源代码可在这里下载 Example.java

1. 载入数据

第一步, 将图数据载入 到一个prefuse 图 Graph 实例中。首先观察 一下 这个文件的内容: socialnet.xml (这个文件 也可在prefuse 发行包里的 data 目录中找到)。注意 ,那些节点有两个数据属性: 一个 name 字段和一个 gender 字段。 以下代码展示了如何使用 GraphMLReader 类( GraphReader 类的一个实例 )来将GraphML 格式 的文件 socialnet.xml 载入到一个prefuse Graph 数据结构中

Graph graph = null;

try {

graph = new GraphMLReader().readGraph("/socialnet.xml");

} catch ( DataIOException e ) {

e.printStackTrace();

System.err.println("Error loading graph. Exiting...");

System.exit(1);

}

这段代码尝试载入这个图,如果出错 了, 则会给出错误 码(任何 不等于0的退出码 都表示出错 )并且退出。 这里详细说一下 readGraph 方法 的参数。 为什么这里传个 "/socialnet.xml" 就行了? 这是因为数据读取器尝试 用多种方法来解释 这个文件名。首先, 它检查一下这个字符串是不是一个URL (例如, http:// ftp:// file:// 开头 ),如果是的话,则打开一个URL连接。如果 不是, 它检查一下这个字符串是不是指向Java 运行 时类路径(classpath)里的某个资源。由于prefuse 发行包里的 data 目录已经包含在类路径里了,所以 "/socialnet.xml"应当能够正常载入 --它位于类路径的根目录中。最终 ,如果 这个字符串不能被解释成 类路径中的一个资源, 则它会被当成文件系统 中某个文件的路径。

如果妳在载入文件时有问题, 则把prefuse 的data 目录添加到类路径中,或者改变文件 的位置。例如,改成 http://prefuse.org/doc/manual/intro/socialnet.xml 就没问题了。无论如何 ,最终结果 就是socialnet.xml 文件 的内容被读取到图中去了。

2. 可视化对象

现在我们需要为这个图创建一个可视化抽象 要做到这一点, 我们首先创建 一个新的 Visualization 实例,并且 将图数据添加到其中。 我们将刚载入的图注册为数据分组名字“graph”。稍后 会使用这个数据分组名字来访问这些可视化数据。 当妳将 Graph 或Tree 实例添加到可视化对象时, 会同时自动注册另两个 子组: 一个是节点集合(加上 一个后缀 ".nodes"),另一个是边的集合(加上 一个后缀 ".edges")。 在这个示例中,稍后会看到怎么使用子组。

// 将此图加入到可视化对象中,设置分组 名为"graph"

// 节点和边的集合可通过"graph.nodes"和"graph.edges"访问

Visualization vis = new Visualization();

vis.add("graph", graph);

3. 渲染器和渲染器工厂

下一步,设置渲染 器( Renderers ),它们 将用来绘制可视 化对象中包含 的可视化条目( VisualItems )。默认情况 下, 可视化对象已经包含了一个 DefaultRendererFactory 实例, 它会使用 一个 EdgeRenderer (默认 会绘制直线 的边 )来绘制所有的EdgeItems,使用 一个 ShapeRenderer 它会将条目绘制成基本形状,例如□和△ )来绘制所有其它的条目。由于 我们想要看到节点 中出现文本标签,所以 我们创建 一个新的 LabelRenderer ,并且告诉它使用"name" 这个数据字段来作为标签 的文字内容。 我们还告诉渲染器要给文字标签绘制一个圆角 这样看起来更光滑。然后 我们创建一个新的DefaultRendererFactory, 它会 将刚才新建的文本标签渲染器作为所有 非边条目的默认渲染器(所有 EdgeItems 会使用之前提到的默认 EdgeRenderer 来渲染 )。 DefaultRendererFactory还有狠多其它的功能,我们目前没有用到--我们也可以设置默认的边渲染器,还可以添加任意数量 的规则 来控制渲染 器的分配(参考编程接口文档)。

// 针对NodeItems,绘制其"name"标签

LabelRenderer r = new LabelRenderer("name");

r.setRoundedCorner(8, 8); // 圆角

// 创建一个新的默认渲染器工厂

// 针对所有的非EdgeItems条目,返回我们的名字标签渲染器

// 针对EdgeItems包含默认的直线边渲染器

vis.setRendererFactory(new DefaultRendererFactory(r));

4. 处理动作

现在我们可以设置可视化编码了。创建 Action 模块 ,它们会处理可视 化对象中的 可视化条目 我们首先创建一些颜色动作(ColorActions)。默认情况 下,每个可视化条目支持三个颜色值:边框 、填充和文字颜色。边框颜色 指的是线条和轮廓的颜色,填充颜色 是指条目的内部颜色,文字颜色 是指任何 的文字和标签的颜色。所有颜色 的默认值都是完全的透明色,所以默认情况下 不会绘制任何东西。 在prefuse 中,每个颜色 值都被编码为单个整数, 它表示的是RGBA(red-green-blue-alpha)值,其中每个分量的范围是0到255 Alpha表示的是透明度,0表示完全透明255表示完全不透明。 ColorLib 类提供了一些好用的方法,可用来创建颜色值。

要想 为社交网络中的人根据性别设置不同颜色的话, 我们首先创建一个自定义的调色板。 这其实是一个由允许的颜色值组成的数组。 在这个示例中, 我们创建 一个数组,其中粉红代表女性,婴儿蓝代表男性。然后 我们创建一个 DataColorAction 它会计算颜色的分配。DataColorAction 的构造函数需要以下参数

  • •. 要处理的数据分组的名字( 在这个示例中就是 graph.nodes

  • •. 以之为基础进行编码的数据字段的名字( 在这个示例中是 gender

  • •.字段的数据类型,可以是以下之一: NOMINAL (各类标签组成的集合) ORDINAL (有序表) NUMERICAL (数字)

  • •. 要设置的颜色字段, 一般是 stroke fill text 颜色字段中的一个。

  • •. 一个可选和调色板(如果 这里不指定调色板,则会创建一个默认的调色板 )。

关于顺序,有一点要注意:DataColorAction 将NOMINAL 和 ORDINAL 数据的值按照它们的自然排序规则来排序,对于文本字符串 来说就是字母顺序。 这就是调色板 中粉红 色排在前面 的原因,女性英文female 的'F'位于男性英文male 的'M'前面。

类似地, 我们使用 ColorAction 组件来将节点 的文字设置成黑色,将 边的线颜色设置成 浅灰色。ColorActions可用来 为所有条目设置一个默认的颜色值, 但同样可支持任意数量的附加规则,以进行 更复杂的颜色分配。

最后,我们创建一个 ActionList 实例, 它将所有 的颜色分配动作组合成一个单独的可执行单元。

// 创建我们的普通调色板

// 粉红色表示女性,婴儿蓝表示男性

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 edges = new ColorAction("graph.edges",

VisualItem.STROKECOLOR, ColorLib.gray(200));

// 创建一个动作列表,包含所有的颜色分配

ActionList color = new ActionList();

color.add(fill);

color.add(text);

color.add(edges);

接下来,我们创建一个单独的动作列表(ActionList), 它提供一个 动画效果的布局。所有 的动作实例都可以 被配置为只运行一次(默认情况),或者在一段指定的时间里持续运行。通过 将持续时间的值设置成无限( INFINITY ),我们 可以让 这个ActionList 永远运行,这将引起布局持续 地更新。然后 ,我们添加一个基于力学的布局器( ForceDirectedLayout ), 由它来为图中的元素分配空间位置。 我们还添加一个 重绘动作( RepaintAction ), 以便在布局被重新计算时告之对应 的显示对象要重绘。

// 创建一个动作列表,它实现 了带动画效果的布局

// INFINITY参数告诉动作列表要永远运行

ActionList layout = new ActionList(Activity.INFINITY);

layout.add(new ForceDirectedLayout("graph"));

layout.add(new RepaintAction());

现在我们将这两个动作列表添加到可视化对象中。 这将导致那些动作被正确地注册到这个可视化对象中,稍后它们 被调用的时候 就能访问这个可视化对象了。每个注册 的动作也会被赋予一个唯一的名字,以便日后调用。

// 将动作添加到可视化对象中

vis.putAction("color", color);

vis.putAction("layout", layout);

5. 显示和交互控制器

我们还需要为这些可视化的数据创建一个显示对象( Display )。 这里创建一个 新的显示对象实例, 被配置为 从可视化对象中拉取所有的可视化条目( 还可以提供一个断言( Predicate )对象, 它控制的是 这个显示对象会处理哪些条目 )。 我们还 为这个显示对象设置一个适当 的尺寸,以像素为单位。然后 ,我们向显示对象中添加3个交互式控制器: Display:

  • •. 一个 DragControl 可使用鼠标左键来 将可视 化条目拖动

  • •. 一个 PanControl 可使用鼠标左键抓住显示对象的空白位置 来拖动整个显示区域

  • •. 一个 ZoomControl 可使用鼠标右键 上下拖动来缩放 这个显示对象

我们使用这些控制器的默认设置。 可以使用对应 的构造函数来改变触发 这些控制器的鼠标按钮和其它设置。

// 创建一个新的显示对象, 它为从我们的可视化对象中拉取数据

Display display = new Display(vis);

display.setSize(720, 500); // 设置显示对象的尺寸

display.addControlListener(new DragControl()); // 拖动条目

display.addControlListener(new PanControl()); // 抓住背景就可以拖动整个显示对象

display.addControlListener(new ZoomControl()); // 右键上下拖动就可以缩放

6. 启动可视化程序

快要完成了!剩下 的事情就是将这个显示对象添加 到一个新的程序窗口中,再让东西都运行起来。 我们创建一个新的 JFrame 实例(Java Swing 用户界面开发 包中的顶级窗口类 ,设置 好它的标题, 让程序在窗口被关闭时退出。然后添加 我们的显示对象, “填充”(pack)窗口(确保窗口 中的部件 -- 在这个示例中只有我们的显示对象一个部件 -- 被正确地布局了 ),显示出窗口。最后 我们运行颜色分配动作列表,确保每个条目 都被分配了适合的颜色,然后 让那个永远运行的布局动作列表开始运行。

// 创建一个新的窗口,用来 装下这个可视化对象

JFrame frame = new JFrame("prefuse example");

// 确保程序在窗口被关闭时退出

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.add(display);

frame.pack(); // 在窗口中将组件布局起来

frame.setVisible(true); // 显示窗口

vis.run("color"); // 分配颜色

vis.run("layout"); // 启动动画布局

总结

妳可以下载完整的示例文件 Example.java 在妳把这个示例运行起来之后, 试着替换 掉其中的一些组件。例如, 妳可以去掉INFINITY 参数 ,让那个负责布局的动作列表只运行一次,然后尝试 一下 这个库里提供的 其它 图布局器

另外,prefuse 发行包的 demos 目录里有狠多其它类型 的示例程序。如果 妳消化 了以上的这个示例,那么妳可以去研究一下其它示例了。

Your opinions
Your name:Email:Website url:Opinion content:
- no title specified

HxLauncher: Launch Android applications by voice commands

 
Recent comments
2017年4月~2019年4月垃圾短信排行榜Posted at:Thu Sep 26 04:51:48 2024
Qt5.7文档翻译:QWebEngineCookieStore类,QWebEngineCookieStore ClassPosted at:Fri Aug 11 06:50:35 2023盲盒kill -9 18289 Grebe.20230517.211749.552.mp4