admin 管理员组

文章数量: 1184232


2024年5月10日发(作者:直线编程)

wxPython界面设计入门及进阶

作者:Justin@JinRuiGarden

原文整理自:/blog/archives/434等

1wxPython界面设计利器:wxFormBuilder

之前我曾经介绍过wxPython界面设计的工具BOA(见这里),但是那个主题只有一篇文章,不是

因为我太懒,而是BOA在稳定性和工具风格上不太合我的胃口。相对于功能追求全面而强大的BOA,

wxFormBuilder则只专注于UI的设计,并生成框架代码,和GTK的工具Glade非常相似。

wxFormBuilder并不是为wxPython而生,它不仅可以生成Python代码,还支持生成C++

和XRC代码。的确是使用wxWidget用户的福音!

wxFormBuilder对于初始次用的用户来说,确实上手不太容易,因为在它的工程中,无法看

到一整个()。在wxFormBuilder的概念中,UI的承载容器是:Frame、Panel、Dialog、

MenuBar和ToolBar等组件。所以在创建好这些UI组件之后,还需要手动创建一个()使

这些组件能够展现给用户。

使用wxFormBuilder进行设计的步骤是:

1、首先增加上述所说的组件;

2、在组件中放入各种Sizer;

3、添加各种控件;

4、添加控件响应动作;

5、自动生成代码;然后就可以根据自己的需要,对代码进行重新组织了。

在这个过程中,wxFormBuilder只负责界面布局、事件绑定和事件接口初始化的部分;剩下的完

全由用户来发挥了。

2wxFormBuilder入门

在上一篇博客中,我专门介绍了wxPython的UI设计工具:wxFormBuilder。这篇博客中将对

wxFormBuilder进行细致深入的介绍。

此文注定是一篇长长的文章,一共分为如下几个部分:1、wxFormBuilder的安装;2、创建工程前

的准备;3、创建第一个工程;4、编写业务逻辑代码。

本文中示例所使用的操作系统是Ubuntu10.04LTS,wxFormBuilder版本为3.2.3-beta。

1

2WXFORMBUILDER入门

第一部分:wxFormBuilder的安装在Ubuntu中安装wxFormBuilder可以选择从Launch-

pad上下载,地址:

/~wxformbuilder/+archive/release

对于其他Linux发行版,可以通过系统自带的软件包管理器进行检索;如果无法通过软件包管理

器进行安装,可以从wxFormBuilder的网站上获取:

/apps/wordpress/wxformbuilder/downloads/

第二部分:创建工程前的准备首先,介绍一下我在这篇博客中将要实现的工程的功能:1、对用户输

入的字符串进行Base64编解码;2、对用户指定的文件进行Base64编解码,将结果保存到另外的文

件中。这个工程主要介绍UI部分的设计,我画了一份手写稿如下:

这个窗口中,大体上分为两个部分:上半部分是对字符串进行编解码的操作空间;下半部分是对文

件进行编解码的操作空间。上下两个部分是基本对称的。继续观察上部分空间,可以发现,这个空间可以

再分解为两个部分:上面的部分是字符串输入与输出的空间,下面的部分是两个操作按钮。继续分解上

面的字符串输入与输出空间,这个部分很像汉字中的“田”字,左侧两个窗口中显示的是标签,右侧的两

个窗口中显式的是用户输入/输出的字符串。这样一步步分解下来,这个窗口的组成就十分清晰了,在下

图中进行了标注:

上面这部分内容,通过对UI设计的草稿进行分解,使得UI的结构变得很清晰;这些框框在

wxPython中有专门的名称,叫做“Sizer”。而sizer是wxFormBuilder设计的基础。

2

2WXFORMBUILDER入门

第三部分:创建第一个工程好了,是时候通过wxFormBuilder进行创作了。要想将上面图片中

的各个按钮、文本输入框等组件组合在一起,首先要有一个“容器”来装载,这个容器可以是一个窗

口(Frame)、面板(Panel)或者对话框(Dialog)。所以,首先到“Forms”面板中选择“Frame”容器。

wxFormBuilder是一个wysiwyg的IDE,即刻就可以看到你选择的Frame。注意:Frame的属性

中,有一个属性是“name”,这个属性就是最终生成代码中Frame对象的类名。

OK,有了Frame之后呢,就要提到上个章节中的Sizer了,可以说掌握Sizer是掌握wxForm-

Builder设计的关键。我首先将设计好的Sizer贴上来,然后和上面的图片进行关联讲解,图片如

下:

这张截图中,gSizer1就是上图中的蓝色框体部分,它的类型是wxGridSizer。wxGridSizer的

图标就像一个“田”字格,可以指定“田”字中行和列的数量。根据草稿的描述,gSizer应该是一个两行一

列(2X1)的Sizer。gSizer2与gSizer3并列于gSizer1中,显然,它们对应的是草稿中的绿色框体

了。并且,与gSizer1一样,都是2X1的Sizer。接下来是fgSizer1,这个Sizer与前面提到的Sizer

不同,它属于wxFlexGridSizer,对应于草稿中的红色“田”字格。剩下还有一个bSizer1,这是另外一

种Sizer,称为“wxBoxSizer”,也是最简单的一种Sizer。它的属性只有一个:组件的排列方向(水平

还是垂直摆放)。按照上面的步骤,将组件排列好之后,按F8生成代码。这样就完成了UI部分的设计。

但是请注意,F8所生成的代码并不能直接运行,因为要展示这个Frame,需要首先创建一个

程序,可以拷贝如下代码到一个py文件中,然后放入与上面生成的代码相同的目录中,运行

这个py程序即可看到我们在上面设计的Frame。

importwx

importBase64CodecMainFrame

#这是F8所生成的代码;

app=()

main_frm=64CodecFrame(None)

计的Frame

main_()

op()

运行之后,就可以看到这个Frame了,但是工作到此还没有结束,因为Frame中有4个按钮

(Button),用户需要点击这几个按钮来实现不同的功能。以“EncodeString”为例,我们希望用户点

3

#这个类是我们设

3WXFORMBUILDER进阶:通过类继承实现UI和处理逻辑的解偶

击这个按钮之后,能够在“Result”右侧的文本框中输出编码后的结果,这就涉及到UI设计的另外

一个问题:定义按钮的响应事件,这是实现UI交互的关键。选中这个Button之后,选择右侧的“事

件(Events)”页签,这个页签中显示了这个按钮所能够触发的各种不同的事件,比如点击按钮就是

“OnButtonClick”,比如我们希望点击按钮后就可以进行字符串的编码,可以这样设置:

这样将所有按钮的动作设置完成之后,UI部分的设计才算结束,重新按F8生成代码吧。

第四部分:编写业务逻辑代码业务逻辑部分的代码,主要是对上一部分最后定义的按钮动作进行处

理。比如我们定义了“EncodeString”接口,那么在生成的代码中,这个接口就需要我们来实现预设定

的编码处理逻辑。代码部分如下:

defEncodeString(self,event):

try:

importbase64

except:

self.m_ue("ERROR:CouldNOTloadmodule``base64''")

return

_istr=self.m_ue()

_ostr=None

try:

_ostr=string(_istr)

except:

self.m_ue("ERROR:CouldNOTdecodestring:%s"%_istr)

return

self.m_ue(_())

()

return

这部分就不做细致的叙述了,完整的代码见附件。

至此,整个wxPython工程就完成了。当然,这个工程只是个Demo,仅作示例用。其中有很多不

完善之处,以及设计不合理的地方,具体细节后面继续探讨。

3wxFormBuilder进阶:通过类继承实现UI和处理逻辑的解偶

在上一篇文章“wxFormBuilder入门”中,通过wxFormBuilder设计了应用程序的界面,并且

可以运行了。但是这款应用程序仅仅停留在可以运行的阶段,从设计、维护的角度分析,还存在众多缺

陷。在本文中,会结合wxFormBuilder工具,谈一谈如何使这款应用更加易于维护。

本文中主要阐述一个问题:如何将GUI设计和业务逻辑设计剥离。wxFormBuilder提供了非常

强大的自动生成代码的功能,这也是我们选择wxFormBuilder的主要原因。但是使用过后,会发现如

4

3WXFORMBUILDER进阶:通过类继承实现UI和处理逻辑的解偶

果在通过wxFormBuilder设计完UI之后,后期UI如果稍有变化,那么就必须重新合并UI部分和

我们定制的业务逻辑代码。

针对这种情况,面向对象思想中,通过“类继承”可以非常容易的避免这种问题带来的麻烦。首先看

下图:

在上面的UML中我们要设计一个查找窗口(FindDialog),其中包含了两个类:FindDialog-

Base与FindDialog,并且后者继承于前者。在设计的过程中,FindDialogBase类完全由wxForm-

Builder设计并自动生成代码。FindDialog在继承之后,除了显示查找窗口外,还有一个额外的需求:

能够记录下用户所有的查找记录。

下面对这个需求进行一下简单的分析:

1、每次用户点击查找进行所有的时候,将用户输入的内容进行记录;

2、当用户关闭查找窗口,或者点击“Quit”结束查找的时候,将记录的条目固化到硬盘上;

3、下次用户调出查找窗口的时候,从硬盘上读取上次保存的条目,并初始化到查找输入框的下拉选

单中。

通过以上的分析,自然可以看到,在子类FindDialog中需要一个保存用户输入条目的变量,并且

需要在初始化(构造)和退出之时加载和保存此变量的值到硬盘上。实现类继承的代码如下:

classFindDialog(FindDialogBase):

'''ImplementtheFindDialog;'''

def__init__(self,parent,filename=HIST_FILENAME):

FindDialogBase.__init__(self,parent)

#Thehistoryfilenane;

lename=filename

#Thefindhistory;

story=[]

#Disablethe**Find**Button;

self.m_(False)

#Initializethefindhistory;

self.__InitFindHistory()

#InitializetheStringComboList;

self.__InitFindComboBox()

#Setwindowfocus;

self.m_us()

5

3WXFORMBUILDER进阶:通过类继承实现UI和处理逻辑的解偶

代码比较简单,就不一一解释了。详细的代码请看附件FindDialog。

这样通过类的继承,就将UI与业务处理逻辑进行了剥离,实现了解偶。比如,在用户的时候过程

中,还会不断提出新的需求,比如:

1、增加复选框,用于指定是否大小写敏感;

2、对输入内容进行过滤;

3、向前搜索,向后搜索;

4、……用户的需求会一直不断变化,唯有实现了UI和处理逻辑解偶,才能更加从容的应对变化。

6


本文标签: 进行 代码 部分 设计 用户