秉承着开源软件的优良传统 Python有一大堆的GUI库 可以支持图形用户界面的开发 有简单易用的瑞士军刀如Tkinter 也有无坚不摧的超级火炮如PyQt 在本课程中 我们在两者之间取个折中 选择了依托于wxWidgets的 wxPython来进行GUI开发 wxPython提供了 对于所有我们需要的UI组件的支持 执行快速 还支持跨平台运行 我们来创建一个简单的wxPython程序 这是一个最简单的app 为了说明创建一个最简单的GUI程序 在这里还没有把这个程序 按照面向对象的思想来设计 我们先用最简单的方式来说明一下 一个简单的GUI程序是怎么样工作的 一行一行看一看这个代码 第一行“import wx” 它表示导入wx的包 一旦你导入了wx模块 就可以创建你的 应用程序(application)对象和框架(frame)对象 这两个对象都是 一个wxPython GUI程序所必需的 第二句 这是用来创建一个应用程序对象 用来执行像消息循环这样的一些动作 下面一条 它是创建一个frame对象 就是一个框架 frame是其他UI组件的容器 要是没有frame 就无法显示GUI了 接下来这句用来显示窗体 第五句“MainLoop()” 它的功能是进入事件循环 它没有自己的代码 只能够读事件找函数调用 但是它是必须要写的 否则没有任何的响应 我们来演示一下这个程序 看一下它的执行结果是什么样的 执行一下这个程序 这就是程序的执行结果 包含一个主要的窗体 有自行设定的标题栏 除此之外就啥也没有了 非常的简单 利用我们前面所介绍的面向对象的知识 我们可以用面向对象的方法 把这个简单的小程序 重新以面向对象的方式来实现 来看一下 我们将从wx库标准的App类中 派生我们的子类 前面我们说过 派生子类的好处就是 最大限度地利用原有的功能 仅仅加入在我们需求中特有的功能 在这个例子中 我们唯一特殊的要求就是跟之前一样 定制标题栏 在这个程序中 这行代码的功能是 定义一个应用程序的初始化方法 我们通常在OnInit() 方法中创建frame对象 OnInit()方法在应用程序开始时 并在MainLoop 也就是我们之前介绍的主事件循环 开始之前就被wxPython系统调用 这个方法会返回一个布尔值 在使用的时候健壮性比较好 所以经常会用到 这个例子只是将应用程序的 标题栏显示“Hello, World!” 框架的主体部分是空的 如果要在标题框架中显示“Hello, World!” 必须在框架中添加一些必要的组件 我们来看一下有哪些组件 第一个是组件容器 它可以用来容纳其他组件 比如说Panel 它存在在一个frame当中 这个是非常常用的 另外还有类似于 可以被用户编辑的动态组件 比如说Button ListBox、TextCtrl这些也都比较常用 还有一些只能显示信息用 不能被用户编辑的静态组件 另外还有一些其他的组件 我们后面有一些会用到 到时候大家可以看一下 我们之前介绍的 HelloWorld示例程序非常简单 除了在标题栏中 显示出一个“Hello, World!” 并且能和普通窗口一样 控制大小和关闭以外 其他啥也做不了 如果你想在你的窗口中显示如 文本、按钮、菜单的话 就得定义自己的Frame类 在Frame类中进行自己的布局 接下来 我们要对前面这个简单的示例程序 做一个小小的调整 也就是把“Hello, World!”文本显示到 窗体中去 而不是标题栏里面 为了简单起见 这次我们不通过派生的方法 修改wx.App()的行为 而是把重点放在派生Frame的子类上 修改了原来Frame子类的__init__()方法 除了仍然调用 父类的__init__()方法 进行类似于窗口标题的设置 位置 大小 这些内容的设置以外 还通过Panel、TextCtrl 增加一个文本输入框的位置 并且把它的 初始文本内容设置成“Hello, World!” 程序运行的结果是这样的 是不是高级了一些 在这个程序中 这些UI组件的放置关系是这样的 TextCtrl的父窗口是Panel Panel的父窗口是Frame 这个程序的功能是显示出 “Hello, World!”字符串 但是绝大多数的GUI程序 不仅仅是为了显示信息用的 我们希望它能够让用户通过操作鼠标 或者是键盘进行控制或者提供用户的输入 为了做到这一点 GUI库要提供事件处理机制 事件可以是低级的用户动作 比如说鼠标移动 或者是按键按下 也可以是定义在wxPython的 窗口部件中的一些高级的用户动作 比如说单击按钮和菜单选择等等 事件可以产生自系统 比如说关机 你甚至可以创建你自己的对象 去产生你自己的事件 wxPython应用程序通过将 特定类型的事件和特定的一块代码 相关联来工作 它们被称为事件响应方法 或者事件处理函数 事件响应方法在响应事件的时候执行 事件被映射到代码的过程就称为事件处理 比如说当产生鼠标移动事件的时候 OnMove()方法被自动调用 任何的wxPython对象都能产生事件 比如按钮、菜单还有其他的窗口部件 下面我们将通过一个例子来演示 怎么样将用户事件和处理逻辑 连接在一起 这个例子当中 panel和frame的创建就跟之前是一样的 不一样的 是在__init__()的最后一行 这一行 大家可以先看一下 我们做了一个调用 这个函数的功能是这样的 它是将鼠标左键抬起事件(EVT_LEFT_UP) 就是 它绑定到派生出的子类 onClick()方法上 这样当用户在窗口中 按下鼠标左键抬起的时候 onClick()方法就会被调用 然后执行我们在这个方法中定义的操作 我们看 这里面的操作有 获得鼠标单击的位置 然后在这个位置上放置 一个静态的文本控件 控件上的文字是“Hello, World!” 大家可以猜一猜 这个程序的效果是什么样的 我来演示一下这个程序 执行一下这个程序 出错了 在这种情况下我们需要做一件事情 “del app” 具体原因比较复杂 我们就不去深究了 我们再来执行 看一下效果 按一下鼠标左键抬起以后 它的效果是什么样的 在哪里按哪里就会出现“Hello, World!” 好玩吧 大家跟我一起说一下 这是什么呢 这是鼠标左键抬起事件 绑在panel的OnClick()方法上 是不是这样的 这里的几个名词要搞清楚