.. include:: ../LINKS.rst wxPython =============================================================================== 虽然已经有一个完整的桌面通讯录了。可是小白并不满足,因为界面太丑了,而且也没有通常的软件那些的菜单栏,工具栏等。 他希望在MM面前秀一番,不想再被鄙视了。于是,小白决定,在给MM用之前,先改进一下自己基本 Tkinter 的通讯录。 小白还记得 Python 邮件列表的朋友推荐过 wxPython。wxPython 对 Windows 有更好地支持,而且提供更多的类库。于是,他决定,用 wxPython 重新写 通讯录。 虽然从来没有用过 wxPython ,但是已经有了用 Tkinter 做软件的经验,小白对学习过程还是有一个比较粗略的思路,首先,应该先安装 wxPython , 然后,找一个简单的可以运行的 wxPython 程序,接着了解 wxPython 的基本元素 (widget),学习布局管理器 (layout manager) 把这些 基本元素合理摆放,最后通过事件处理,使菜单,工具栏和搜索等按钮调用以前写好的添加、搜索、删除等通讯录操作函数。 小白挽起袖子,开工!先安装 wxPython 吧。 一、wxPython 程序库安装 ---------------------------------------------- 小白用 "wxPython download" 在必应上搜索了一下,在搜索结果的第一项中,直接找到了 wxPython 的下载页面,如下: http://www.wxpython.org/download-2.6.4.0.php wxPython 的下载页面很详细地介绍了各个操作系统,如 Windows, Linux/Unix ,和 Mac 的安装方法。小白暗想,那些用 linux/unix 操作系统的 都是天才,他们根本不用看,肯定会安装。比如 Ubuntu下,打开 console, 输入 "sudo apt-get install wxPython" 就可以了。小白 虽然还是个菜鸟,可是幸好 Windows 下安装并不难。只需要下载正确的版本,用鼠标点击就可以完成安装了。小白用的是 Windows XP 操作系统, 使用的 Python 2.5。于是小白下载了 Python 2.5 的 win32-Unicode。下载完后,小白点击那个.exe文件,一路点击"下一步"完成了 wxPython 程序库的安装。 在 wxPython 的下载页面,小白发现,wxPython 还提供一些文档和示例。小白把 win32-docs-demos 也下载下来,安装了。不过,用 wxPython 编写界面,并不需要安装 win32-docs-demos。 小白打开 Python IDLE ,输入下面的代码,尝试导入 wxPython 的库函数。 >>import wx 恩!没有报错。说明用 Python +wxPython 的开发环境已经配置好了。 二、入门程序,Hello, wxPython -------------------------------------------------------------------- 和 Tkinter 的学习过程一样,小白决定先从网上找一个 wxPython 的最简单程序。 "用 wxPython 写个 Hello, wxPython 程序吧。" 小白发现 wxPython 的官方网站(www.wxpython.org)有一个 wiki ,提供了很多简单的示例程序和丰富的文档。小白参照最简单的入门 程序,略做修改,写出了一个 Hello, wxPython 的程序。参见源代码 wx/HellowxPython.py 。 .. literalinclude:: ../../src/3_guimala/wx/HellowxPython.py 在上面的示例中, 小白先建立了一个面板 (wx.Panel) 和一个文本标签(wx.StaticText),然后用布局管理器 (wx.BoxSizer) 将文本标签放到面板上。 点 F5 看看什么样吧。 .. figure:: ../_static/snap/gui_wx_HellowxPython.png 图1. Hello wxPython 界面 三、GUI 图纸施工 ----------------------- wxPython 的基本元素(widget) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 小白希望给软件增加菜单栏和工具栏。于是他打算先了解 wxPython 的基本元素。于是,他分别搜索了 "wxPython menu bar" 和 "wxPython tool bar" 。通过搜索,他了解到,wxPython 主要有以下这些基本元素: Button ,ToggleButton ,BitmapButton ,StaticLine ,StaticText ,StaticBox ,ComboBox ,CheckBox ,StatusBar ,MenuBar, RadioButton ,Gauge ,Slider ,ListBox ,SearchCtrl, SpinCtrl ,SplitterWindow ,ScrolledWindow , Notebook ,Panel 等。 根据新的需求,和 Tkinter 编程的经验,小白记下了他可能用用到的一些元素,如 Button, StaticText, ListBox, MenuBar,StatusBar 和 SearchCtrl。了解了wxPython的基本元素后,小白打算尝试写一个具有菜单栏和工具栏的简单界面。小白修改了HellowxPython.py, 得到了一个新的具有菜单和工具栏的界面。参见源代码 wx/MenuToolBar.py 。 .. literalinclude:: ../../src/3_guimala/wx/MenuToolBar.py 小白点击 F5 运行 MenuToolBar.py ,发现这个界面包含菜单和工具栏,分别有一个退出功能(仅仅有样子,还不能真正地退出,需要 学习事件绑定后,才能完成退出动作)。主界面上有一个 StaticText 显示 "Hello wxPython". .. figure:: ../_static/snap/gui_wx_MenuToolBar.png 图2. 通讯录菜单和工具栏 随后,小白根据学习 Tkinter 的经验,学习了 Button, SearchCtrl, ListBox 这三个元素的使用方法。Button, SearchCtrl, ListBox 分别用于 搜索按钮,搜索输入框和呈现搜索结果。 wxPython 的布局管理(Layout manager) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 了解了需要用到的元素后,接着,小白需要合理地摆放这些元素。虽然他还不知道 wxPython 如何布局,不过小白已经使用过 Tkinter 的 布局管理器。根据以往经验,小白搜索了 "wxPython layout" 和 "wxPython 布局管理" 。经过搜索以及阅读相关结果,小白发现, wxPython主要有 BoxSizer ,StaticBoxSizer ,GridSizer ,FlexGridSizer ,GridBagSizer 这几种布局管理方式。 BoxSizer 将元素以行或者列地方式摆放。一个 BoxSizer 还可以包含另一个 BoxSizer 。BoxSizer 的使用方式如下: box = wx.BoxSizer(integer orient) 首先定义一个 BoxSizer,然后将元素加入到 BoxSizer 里。放置参数 integer orient 可以是 wx.VERTICAL 或者 wx.HORIZONTAL,分别以纵向或者横向的方式放置元素。 GridSizer 以二维坐标的方式放置元素。每个坐标的元素具有相同的大小。 GridSizer 的使用方式如下: :: grid = wx.GridSizer(int rows=1, int cols=0, int vgap=0, int hgap=0) FlexGridSizer,与 GridSizer 类似,也是使用二维坐标的方式放置元素。不过,FlexGridSizer 比 GridSizer更自由。同一行内的元素都具有相同的高度,同一列中的元素具有相同的宽度。但是不同行或者之间的元素的高度或者宽度,可以不相同。FlexGridSizer 的使用方式如下: :: wx.FlexGridSizer(int rows=1, int cols=0, int vgap=0, int hgap=0) GridBagSizer 是 wxPython 中最为复杂的布局管理方式。GridBagSizer可以更直接地指定元素的具体位置。每一个元素都可以覆盖多行或者多列。GridBagSizer 的使用方式如下: :: wx.GridBagSizer(integer vgap, integer hgap) 小白的通讯录只有三个元素,比较简单,BoxSizer 就可以满足需求。小白分别用 SearchCtrl,Button 和 ListBox 分别创建了搜索条,搜索按钮和搜索结果框。然后用一个横向的 BoxSizer 将搜索条和搜索按钮结合在一起,再用一个纵向的 BoxSizer加入搜索结果框。代码如下 (或参见源代码wx/wxLayoutManager.py。) .. literalinclude:: ../../src/3_guimala/wx/wxLayoutManager.py 小白点击F5运行wxLayoutManager.py,并将截图放置如下。图中已经具备通讯录的主要界面了。 .. figure:: ../_static/snap/gui_wx_wxLayoutManager.png 图3. 通讯录主界面,展示wxPython的布局管理器 wxPython 的事件处理(Event and Bindings) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ wxLayoutManager.py 中已经具备主要界面了。还差的就是把事件处理函数(包括搜索、增加和删除联系人)与按钮绑定。虽然从来没有用过 wxPython ,但是根据 Tkinter 的经验,小白认为,这应该不难,不就是将按钮绑定(Bind)到函数吗?搜!小白搜索了一下 "wxPython event binding",以查询 wxPython 中事件绑定的具体方法。原来,self.Bind(wx.EVT_BUTTON,self.search,self.search_button)这样就可以了呀?其中 self.search 是事件处理函数,self.search_button 是被绑定的搜索按钮。wx.EVT_BUTTON 为按钮点击事件。 小白决定动手试一试。于是在 wxLayoutManager.py 的基础上增加一个搜索功能。在文本文件中搜索联系人,小白以前在基于 CLI 和 Tkinter 的通讯录中已经使用多次了。唯一需要查询的是,在得到搜索结果后,如何更新 ListBox 这个搜索结果框的值 。经过查询,小白发现Clear()函数可以重置 ListBox 的值,Append("")函数可以在 ListBox 中增加新值。小白在 wxLayoutManager.py 在基础上,增加了搜索联系人的功能。代码如下 (或参见源代码wx/wxEventBinding.py。) .. literalinclude:: ../../src/3_guimala/wx/wxEventBinding.py 完善通讯录 ^^^^^^^^^^^^^^^^^^^^^^^ 至此,小白已经学会了 wxPython 中的基本元素,布局管理和事件响应的方法了。 在 MenuToolBar.py,小白学会了如何创建目录和工具条。仿照 File(文件)目录下退出功能的写法,小白进一步完成了 Edit(编辑)目录下的添加和删除功能,以及 Help(帮助)目录。 在 Tkinter 一节,小白学会了如何使用 Tkinter 创建新建联系人界面的方法。新建联系人界面对于 wxPython 来说,主要是 StaticText 和 TextCtrl 两个元素,分别用于文字标签和联系人信息输入。然后用 BoxSizer 将这些元素摆放在一起。仿照以上讲的 wxPython 的基本元素和布局管理方式,小白成功地用 wxPython 重写了新建联系人界面。 最后,小白找回了他在写 CLI 通讯录时的删除联系人和保存联系人的函数,通过 wxPython 的事件处理方法,实现了联系人删除、保存操作。小白在使用 Tkinter 时,也实现过保存联系人的函数。本节也详细讲了如何实现联系人搜索操作。将这些曾经写过的函数贴在一起,略做修改。小白很容易的完成了基于 wxPython 的通讯录。他把代码放在了 wx/wxAddressbookzh.py。您也去看看他写的代码吧? .. figure:: ../_static/snap/gui_wx_wxAddressbookzh.png 图4. 通讯录界面