您好、欢迎来到现金彩票网!
当前位置:21点 > 子例程 >

用 PerlTk 实现数据可视化

发布时间:2019-06-27 05:01 来源:未知 编辑:admin

  developerWorks 中国 正在向 IBM Developer 过渡。 我们将为您呈现一个全新的界面和更新的主题领域,并一如既往地提供您希望获得的精彩内容。

  在直观显示数据时,人类的眼睛在识别复杂的行为、运动轨迹和图案时表现得出奇地好。如果一个数据集的数据超过 12个点,那么用图形表示就会有所帮助;如果数据集里的数据超过了数千个点,那么使用图形表示就是必需的了。

  对于简单的 x-y 平面图,gnuplot 经常是第一选择。对更复杂的问题来说,您可以使用 xmgrace 或者其他的绘制工具。但是大多数简单的曲线绘图仪在绘制二维数据方面或者在复杂的图形中进行极为精细的控制方面显得很不足。复杂图形的例子包括专业化的条形图和须状图,带有完整误差的时间序列条形图,颜色编码和密度图,以及许多其他可能的图。

  这就是 Perl/Tk 的闪光之处。前提是,您已经使用 Perl 来进行数据操纵和提取。Perl/Tk 提供了与 Perl 绑定的 Tk GUI 工具集,并且它可能是最容易使用的部件之一。

  在本文中,不会关注 Perl/Tk 的实际用户界面部分(例如,复选框和下拉菜单),只探讨它的绘图能力。

  作为一个 GUI 工具箱,Perl/Tk 提供一个其他 Perl 图形扩展包(例如,极好的 GD 包)中没有的附加工具:即,动画和交互式数据探索的能力。在接下来的示例中我将向您展示这些应用。

  为了介绍 Perl/Tk 编程的基本概念,先让我们考虑大家熟知的“Hello, world”程序,在 Perl/Tk 中,该程序类似如下:

  这个程序首先打开一个新窗口,然后显示文本和一个“Exit”按钮。单击这个按钮,终止程序。(曾经使用过的GUI工具箱有比这个程序更容易的吗?)

  语句use Tk;声明在程序中要引用 Tk 模块。整个 Tk 工具集汲取了大多数 Perl 面向对象的特性。您经常可以看到使用-符号基于对象对方法进行调用。

  每个 Perl/Tk 应用程序必须明确地对应一个主窗口。它是一个“项层”部件,意思是它必须在一个单独的窗口中打开。我们已经使用其构造函数new来说明了这一点。

  下一步,我们将在这个主窗口中创建标签和按钮对象,作为主窗口的子部件。每个部件(除了顶层部件外,比如主窗口)必须是某个确切父部件的子部件。

  我们为标签和按钮部件指定一些参数,然后调用pack,该语句是 Perl/Tk 的几何管理器之一。几何管理器的职责是在父窗口中将子部件有规则地排列起来。除了语句pack外,还有语句grid和place,它们除了布局部件外,更可以对部件进行出色的纹理控制。

  在 Perl/Tk 中,部件的参数用它们的名字来指定(和管理器工具语句pack的参数一样),通常开头带有一个短横。注意那些围绕参数名的引号不是必需的(因此通常被省略掉),因为操作符=将它左边的裸单词(barewords)看作是被引用的字符串。参数-command用来定义回调,如果部件接收到一个用户事件,那么就会触发对将被调用函数的引用(例如,在当前例子中,用户点击按钮)。由于这个回调程序体很小,所以我们将整个函数内嵌为一个匿名子例程来完成。下面您将看到独立子例程被注册为回调程序的示例。

  现在我们的部件已经设置完成,并且程序准备接收用户事件。程序的最后一行调用MainLoop语句,这个语句的作用是开始监听用户事件,并且把它们分派给合适的回调。所有的事件都已被对应的能够产生事件的部件注册。

  整个程序就是这样!注意初学者通常犯的错误是忘了调用pack或者调用MainLoop。如果程序运行时应用程序窗口不能正常显示,原因可能就是由于其中之一或者两者都被遗漏掉所造成的。另外要记住的一点是新窗口的实际大小和位置是由窗口管理器控制的(比如Gnome,KDE,IceWM),而不是由程序本身控制。

  如果我们要输出图形,Tk 提供了画布部件。一旦创建了画布部件实例,其上就可以创建一些标准的图形对象(例如,直线、圆形、长方形等)。以下是示例程序:

  在这个程序中,和前一程序一样,首先创建一个主窗口,并且设置窗口的宽和高为$size像素。resizable( $in_x_direction, $in_y_direction )方法用于固定顶层窗口的尺寸。该方法带有两个布尔变量,用于决定部件在 x方向或者 y方向是否可以调节。这里我们完全禁止调节尺寸。

  下一步是创建画布部件并使之充满整个主窗口。我们已经将画布清理干净(将画布的背景色设置为“白色”),并且当鼠标移至画布时,光标变为交叉(在 X11 中有 78种标准的鼠标光标形状,其名称可以在头文件 cursorfont.h 中找到,典型安装时,这个头文件可以在/usr/X11/include/X11/ 目录中找到。)

  在注释语句 # Place objects on canvas: 之后,我们准备在画布上绘制内容了。我们已经创建了一个大的红色的长方形,并且有一排较小的灰色长方形斜穿过它。注意画布对象使用了标准的“图形坐标系统”,x 轴指向右边,y 轴指向下面,所以坐标系统的原点(两轴交接的地方)位于窗口的左上角。

  这段代码演示了在 Perl/Tk 中指定颜色的两种办法。一种是使用在文件 rgb.txt(通常这个文件可以在目录 /usr/X11/lib/X11/ 下找到)中预定义的颜色名称,比如“red”或者“PapayaWhip”。另一种方法是指定各个 RGB(red/green/blue)值,这个值以“#”打头,后面跟着三个两位的十六进制数的字符串。注意如果某个十六进制数只有个位数,那么在其左边必须补上一个零。如果 RGB 三个值相等(正如本例所示),显示的颜色就是灰色。

  长方形(其他形状也一样)有两种颜色,一种是填充色,另一个是边框色。由于我们没有指定后者,所以默认为黑色。要去除这些边框,设置-outline属性为与填充色相同即可;要加宽边框,使用-width属性来指定宽度(用像素表示)。

  最后,要注意图形元素(像长方形、直线、圆形)都不是部件!诸如createRectangle这样的函数都不会返回一个对象,然而每个图形元素都有一个 ID(确切地说,是一个数字)来标识。要移动、修改或者删除图形元素,该 ID将作为参数传递给包含画布对象的各个成员函数。例如,为了删除红色正方形,我们使用$canvas-delete( $id ),其中的$id就是第一次调用函数createRectangle的返回值。

  从某种意义上来讲, GUI工具箱(例如 Tk)的整个出发点就是为了实现与用户交互。换句话说,工具箱应该使得应用程序响应各种事件变得很容易,例如鼠标点击或者键盘输入。

  在 Perl/Tk 中,大多数部件都有-command属性,正如上面所提及的,该属性允许部件注册一个子例程(“回调”),如果这个部件被用户激活,那么该子例程将被调用。我们已经在清单1中看到了一个这样的例子,其中回调是一个匿名子例程:-command = sub { exit }。如果不采用这种方法的话,我们要想注册一个子例程(用sub method_name{ ... }来定义),那么必须注册一个到这个子例程的引用,类似于:-command=\&method_name。

  画布部件则不同,它不带-command属性。为了使画布能够响应用户的交互,我们需要使用Tk::bind函数显式地将回调绑定到事件。(注意显式命名空间Tk::在这里是必需的,因为画布部件定义了自己的bind函数是隐含继承的)。

  函数bind带有两个变量:第一,要响应的事件序列;第二,回调和它的参数。事件序列是放在尖括号中的字符串,例如,Motion或者Shift-Button-3。(Tk响应的事件是类似于 X11窗口系统定义的事件集,但是不完全相同。请查阅 Tk::bind 的参考资料来获得事件和修饰符的完整列表。)

  函数bind的第二个变量是被调用的回调。我们已经看到如何使用匿名的子例程或者对指定子例程的引用。当回调需要参数时,我们将这个回调指定为匿名列表,首先是子例程引用,然后是后续列表项参数:bind( Motion, [ \&method_name, parameter1, parameter2 ] )。注意方括号(不是圆括号)中需要组成一个匿名列表引用。

  使用bind指派的回调的第一个变量总是一个对产生事件的部件的引用。然后才是用户定义的参数。这是一个非常容易忘记的细节!

  作为最后的难点,Ev()工具允许检索和使用调用回调的事件细节。例如,事件发生的位置坐标(参照$canvas原点)可以通过Ev(x)和Ev(y)获得。

  放到我们第二个示例程序中的MainLoop调用之前,那么当我们在画布窗口中单击鼠标左键时,画布坐标将显示在屏幕上。(注意,在参数列表中,我们省略了第一个条目$_[0]。这是上面提到的对调用部件的引用,在本例中,就是$canvas。)

  作为展示绘制图形和数据可视化能力的重要例子,设想我们面临以下带有两个变量 x和 y的方程:

  仅从研究方程本身很难得到该函数行为的任何想法。此外,这个行为十分复杂,以致即使绘制大量的一维图形(也就是说固定y为某些值,仅仅绘制x函数的值)也不能揭示该方程的底层结构。然而,该函数的简单二维密度绘图马上给我们一种清晰的感觉,那就是在原公式中包含的简单而漂亮的对称结构。

  您可以在本文后面的参考资料中下载这个程序,并完成绘图。根据前面的讨论,这个程序应该容易理解,虽然在这里一步一步地讲解这个程序会过于冗长。注意,这个程序关于处理实际绘图和用户交互的部分十分简短。程序的绝大部分花费在创建和设置各种GUI部件,以及完成从函数的坐标系统到屏幕坐标系统的转换上。这是所有绘图程序的典型特征(并且如果我们允许用户输入要绘制的函数,程序将进一步扩大,这是由于代码必须完成必需的输入验证。)

  在屏幕上看到数据是一回事,将它保存到磁盘中(或者打印出来)又完全是另一回事。Perl/Tk 已经显示了很强的绘图能力和灵活性,但是不可思议的是它竟然没有一个标准的模块用于将图形存储到位图文件中。

  有一个工具用于将画布内容存储到 PostScript 文件中,这就是通过调用$canvas-postscript( -file=file_name.ps )。这将只能捕获在画布中实际显示的内容。因此,要注意的是一定要确保画布对象已经全部渲染到屏幕上;否则输出文件将是空的。函数update()用于(在任何部件上)强制渲染并且等待所有进行的事件全部完成。

  另一种可能是将每一屏幕像素的 RGB 值输出为由三部分组成的字节,并直接写入任何文件句柄。一些图形程序可以处理用这种方法生成的 rgb 文件。可能最为强大的是来自 ImageMagick 软件包的转换实用程序,它能够将 rgb 文件转换成任何常用的图形文件格式。

  最后,从显示窗口获取图形文件的最简易方法是直接拷屏。来自 ImageMagick 软件包的导入工具十分灵活方便,并且可以生成多种文件格式。

http://korinkorin.com/zilicheng/106.html
锟斤拷锟斤拷锟斤拷QQ微锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷微锟斤拷
关于我们|联系我们|版权声明|网站地图|
Copyright © 2002-2019 现金彩票 版权所有