Rainyboy 发表于 2011-9-3 11:04

guidata库使用手记:快速定制科学计算程序的图形界面

本帖最后由 Rainyboy 于 2011-9-3 11:44 编辑

和大多数的Python库一样,guidata有自己的技术支持页面和实例完善的帮助文档,然而文档毕竟是死的,只有使用起来更能体会其中的奇技淫巧。
完整文档:http://packages.python.org/guidata/

概述(译自 guidata documentation/overview)
对于科学计算软件的开发,从最基本的模块直至最复杂的应用程序,开发者都需要灵活地方便地操纵数据(例如,数据处理时输入的参数)。这些数据由多种类型组成:实数(如一些物理量),整数(如数组的索引),字符串(如文件名),布尔值(如某个选项的开关)等等。大多数时候,这类软件需满足如下需求:
1)允许用户在图形界面上输入每一个参数的值,即通过一些控件来对应特定数据类型的输入(例如,一个单选框/一组复选框对应于单选或复选操作)

2)输入的数据必须在程序中由于之对应的方式储存(例如,对于单元数据的储存,难道不应当储存选项的说明字符串和整个选择列表的索引么?)

3)该储存方式同时应当易于使用(例如,在后续的数据处理中易于访问)

4)通过图形界面向用户展示参数的设置,同样,需要使用与数据相对应控件


一个例子:选择指定的实验数据进行对比
需求:
1)用户在图形界面上选择要进行对比的数据组(多选)
2)根据用户的选择绘出指定的实验数据曲线(这一部分工作有Matplotlab完成)
3)当用户完成选择后回显以确认

完整的代码见附件,这里需要说明的是上述需求1)和3)的实现全在函数editFromGUI(fnameList)中:
def editFromGUI(fnameList):
    #_app = guidata.qapplication()
    class ParameterUGI(dt.DataSet):
      choice = di.MultipleChoiceItem("Select files to plot", fnameList)
    param = ParameterUGI()
    while(True):
      param.edit()
      if len(param.choice)!=0:
            break
    param.view()
    return param.choice
参照文档这个函数并不难理解,那么guidata是如何体现“储存的数据易于使用”的呢?见函数main():
def main():
    _app = guidata.qapplication()
    fnameList = ['OnAxis_R.txt','OnAxis_Z.txt','OnBox_Box.txt',
               'OnGear_1.txt','OnGear_2.txt']
    colorList = ['blue','green','black','red','purple']
    markerList =
    lineList = [[],[]]
    labelList = []
    l = editFromGUI(fnameList)
    initPlot()
    for i in l:
      line1,line2=PlotSingleFile(fnameList,colorList,markerList)
      lineList.append(line1)
      lineList.append(line2)
      labelList.append(fnameList)
    plt.figure(1)
    plt.subplot(2,1,1)
    plt.legend(lineList,labelList,5)
    plt.subplot(2,1,2)
    plt.legend(lineList,labelList,5)
    plt.show()
    _app.exec_()
其中,l = editFromGUI(fnameList) 说明 l 引用的正是在函数 editFromGUI中定义param.choice的,显然,这是一个类型为di.MultipleChoiceItem的对象。而在main()函数中,完成对editFromGUI调用后,出现了 for i in l: ,这意味着l同时具有了可遍历的功能(即,l具有list对象对具有的基本访问功能),在这里完全可以当作一个list使用,这正是概述中“3)该储存方式同时应当易于使用”的完美体现!

这个例子运行起来时,会先展示这样一个窗口:



可以选择几项:



点击确定,出现这个窗口:



点击确定后,根据所选读取文件数据并绘制图形:




奇技淫巧:如何让你的对象表现得像个具有特性功能的list
    (当然,这里对象的意思是instance,不是marriage partner)

class rainyboy:
    __index = -1
    def __init__(self,a,b):
      self.list = range(a,b,2)
    def __getitem__(self,key):
      return self.list
    def __str__(self):
      return repr(self.list)
    def __len__(self):
      return len(self.list)
    def __call__(self):
      return 'rainyboy'
    def __iter__(self):
      return iter(self.list)
      return self
    def next(self):
      self.__index = self.__index + 1
      if self.__index == len(self):
            raise StopIteration
      return self.list
对于上面这个类,执行这样的代码:
if __name__ == '__main__':
    c = rainyboy(1,20)
    print c,c,c,len(c)
    print c()
    for i in c:
      print i
会输出:

1 3 10
rainyboy
1
3
5
7
9
11
13
15
17
19


怎么样?C是一个Rainyboy类的对象,C可以像list那样被整个print出来,也可以单独按索引值访问,还可以返回数据的长度,还可以像函数那样被调用,甚至可以迭代访问!这些功能得益于重写或定义了如下函数:
可以像list那样被print出来: __str__
可以按索引值访问:__getitem__
可以求得数据区的长度:__len__
可以像函数那样被调用:__call__
可以迭代访问:__iter__ , next

使用感受
    正如guidata在review中所言,这确实是一款适合为科学计算定制数据输入界面的库类——使用该库类的人只需要关注很少量的图形界面知识,甚至没有定义任何的消息-响应映射。布局(layout)是图形界面设计中很重要的一环,在guidata中甚至也不用刻意设置——前提是你接受它默认的样子。当然,布局是可以设置的,更多的例子可以运行它的示例:
from guidata import tests
tests.run()


smtmobly 发表于 2011-9-4 16:33

你真是一个执着的人

Rainyboy 发表于 2011-9-4 17:44

回复 2 # smtmobly 的帖子

见笑了,边用边学而已。。。
好久没见你出现了,近况如何?

smtmobly 发表于 2011-9-5 20:55

开学了,最近挺好,谢谢哈!有空我常来看的,但是python好久不用了

c39850477 发表于 2013-4-20 21:59

挺好,谢谢哈!
页: [1]
查看完整版本: guidata库使用手记:快速定制科学计算程序的图形界面