转自 http://hi.baidu.com/jingxue1979/item/936180b9224dee40ba0e1295

1. 创建一个显示一个图像的文件包括三步:

   a. 创建一个可以工作的最小wxPthon程序;

   b. 组织和细化;

   c. 显示图像。

2. 创建空的最小wxPthon程序需要完成五个必要的步骤:

   a. 导入wxPython包;

   b. wxPython应用程序类的子类化;

   c. 定义该应用程序的初始化方法;

   d. 创建该应用程序类的实例;

   e. 进入此应用程序的主事件循环。

3. 导入wxPython模块:import wx即可。老代码中包名字是wxPython,包含了一个内在的名为wx模块,可用from wxPython import wx导入。需要注意的是导入wx时wxPython对包中其他模块执行一些初始化工作,因此从wxPython导入其它东西之前需要先导入wx。

4. wxPython程序必须包含应用程序(application)对象和框架(frame)对象各至少一个。应用程序对象是wx.App实例或者在OnInit()方法中定义的子类的实例。OnInit()方法在应用程序对象启动时为其父类wx.App所调用,通常在其中创建框架对象。

5. wxPython application类的子类化中一般不定义一个__init__()方法,此时在对象创建时调用父方法的__init()__即wx.App.__init()__,后者将初始化wxPython并因此调用到OnInit()方法。因此如果自己定义了__init__()方法,需在其中调用其基类的__init()__方法。

6. 进入主事件循环:app = App(); app.MainLoop(),其中App为wx.App子类。app.MainLoop()方法在应用程序的所有框架关闭后返回并退出。

7. 使用App类的SetTopWindow()方法可以定义应用程序的顶级窗口,方法的参数是一个框架对象。

8. wxPython中图像处理可借助wx.Image对象,用法:p_w_picpath = wx.Image(‘wxPython.jpg', wx.BITMAP_TYPE_JPEG)。然后在框架对象里包括此wx.p_w_picpath对象即可。wx.p_w_picpath对象的几种方法:

   a. ConvertToBitmap(),生成位图;

   b. GetWidth(),.GetHeight()分别获取图像长宽参数。wx.StaticBitmap()用于展示框架的bmp。

ii 给你的wxPython程序一个稳固的基础

9. wxPython程序的两个基石:应用程序对象和顶级窗口(top-level window,没有father的框架,而非由SetTopWindows定义的那一个框架)对象。

   应用程序对象用于启动并管理主事件循环,响应于窗口事件,分配与之相应的事件处理器(event handler)。

   顶级窗口通常作为主窗口,负责展示数据和各种工具。

10. 创建一个wx.App子类的步骤:

   a. 定义子类;

   b. 为该子类写OnInit()方法;

   c. 创建该子类的实例;

   d. 调用该实例的MainLoop()方法。

11. OnInit()方法在应用程序开始、主事件循环开始前被wxPython系统调用。这个方法不要求参数并返回一个布尔值,如果所返回的值是False,则应用程序当即退出。

12. 创建__init__方法时需要调用父类的__init__方法,做法:wx.App.__init__(self)。

13. 如果在系统中只有一个的话,一般不自己创建wx.App子类,而是利用类wx.PySimpleApp,用法:app = wx.PySimpleApp()。然后创建框架对象和调用app即可。

14. Py中用于输出文本的两种标准流: 标准输出流sys.stdout和标准错误流sys.stderr。Win下wxPython默认在应用程序对象创建时将标准输出流重定向到窗口中,而Unix下wxPython则不控制标准流。因此推荐明确指定重定向行为。

15. 指定重定向:app = App(redirect=True,filename='some file'),其中filename指定数据输出到的文件。输出到stderr:print >> sys.stderr, ”A pretend error message”。如果指定了重定向,应用程序__init__时输出内容不进行重定向,而OnInit和OnExit方法里进行重定向。

16. 关闭框架。对于顶级窗口可调用Close()方法。正常关闭时可在OnExit方法中做资源清理,如果应用程序关闭后在所有窗口关闭后仍然继续,可以用wx.App的SetExitOnFrameDelete(False),此时应用程序,直到调用wx.Exit()。

17. 紧急关闭应用程序的两种方法,此时将不能进行全部的数据清理工作,慎用:a. 调用wx.App的ExitMainLoop()方法。这个方法显式地使用主消息循环终止,使用控制离开MainLoop()函数。实际上相当于于关闭所有顶级窗口;b. 调用wx.Exit()。

18. wxPython里的wx.EVT_QUERY_END_SESSION事件对应系统关机或注销,将此事件绑定一个handler可以在关机或注销时进行一些清理工作,如保存文档或关闭连接等等。该handler的event参数为wx.CloseEvent。wx.EVT_QUERY_END_SESSION事件的默认处理器调用顶级窗口的Close()方法依次向顶层窗口发送wx.EVT_CLOSE事件,。如果任何一个Close()方法返回False,那么应用程序将试图否决关闭。可用CanVeto()方法决定是否可以否决关闭,Veto()执行否决。

19. 对话框:wx.Dialoag类。

20. 应用程序一时内只能有一个主顶级窗口。如果没有使用SetTopWindow()指定主顶级窗口,则将wx.App的顶级窗口列表中的第一个框架默认为主顶级窗口。

21. wx.Frame的构造器所要求的参数:wx.Frame(parent, id=-1, title=””,pos=wx.DefaultPosition,size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE,name=”frame”)。其中parent为父窗口,对于顶级窗口此参数值为None,框架随其父框架的关闭而关闭;id用于指定新窗口的wxPython ID,如果值为-1则wxPython将为其自动生成一个新的ID;pos参数为一个wx.Point对象,它指定这个新窗口的左上角在屏幕中的位置,(0,0)是显示器的左上角,默认为(-1,-1),即让系统决定;size参数为wx.Size对象,指定窗口的初始尺寸,默认为(-1,-1),即让系统决定;style指定窗口类型;name为框架的内部名称,可用它来寻找窗口,而不同于用于显示的title。所有这些参数将传递给父类的构造器方法:wx.Frame.__init__()。

22. ID的用处:在指定的对象发生的事件和响应该事件的回调函数之间建立唯一的关联。指定ID号的三种方法:a. 构造器中指定,此时需要确保同一框架内没有重复的ID或常量,可以调用wx.RegisterId()来确保在此应用程序中wxPython不在别处使用此ID,另外为使应用程序内ID不重复,应避免wx.ID_LOWEST和wx.ID_HIGHEST之间的ID;b. 使用函数wx.NewID(),让wxPython自动创建;c. 给窗口部件的构造器传递全局常量wx.ID_ANY,或者-1。查看ID:id = frame.GetId()。

23. wx.Point类。用法:point = wx.Point(10, 12); x = point.x; y = point.y。另外可以用函数Set()和Get(),后者返回一个tuple。wx.Point的实例可以像其它Python对象一样作加、减和比较运算。但wx.Point一般用int作为实参,如果需要float型坐标,可使用类wx.RealPoint。

24. wx.Size类实参的名字是width和height,除此之外和wx.Point几乎完全相同。

25. 构造器中不必显式地创建wx.Point和wx.Size实例,只需传递tuple即可,如:frame = wx.Frame(None, -1, pos=(10, 10), size=(100, 100))。

26. 框架的样式可在构造器中和使用SetStyle()方法设定。样式元素都有一个常量标识符,可以借助或运算符|使用多个样式,或者用^操作符从一个合成的样式中去掉个别的样式。

27. 一些wx.Frame中常用的样式:a. wx.CAPTION:标题栏,显示该框架的标题属性;b. wx.CLOSE_BOX:在框架的标题栏上显示关闭框,使用系统默认的位置和样式;c. wx.DEFAULT_FRAME_STYLE:默认样式,带有最大化最小化和关闭;d. wx.FRAME_SHAPED:使用此样式创建的框架可以使用SetShape()方法创建一个非矩形的窗口;e. wx.FRAME_TOOL_WINDOW:给框架一个较小的标题栏,使它看起来像一个工具框窗口,在Win下,此窗口不会出现在任务栏中;f. wx.MAXIMIZE_BOX:框架的标题栏上添加最大化框,使用系统默认的位置和样式;g. wx.MINIMIZE_BOX:框架的标题栏上添加最大小框,使用系统默认的位置和样式;h. wx.RESIZE_BORDER:框架大小改变;i. wx.SIMPLE_BORDER:没有装饰的边框。不能工作在所有平台上;j. wx.SYSTEM_MENU:增加系统菜单(带有关闭、移动、改变尺寸等功能)和关闭框,其中改变尺寸和关闭功能是否有效取决于wx.MAXIMIZE_BOX, wx.MINIMIZE_BOX和wx.CLOSE_BOX样式是否启用。

28. 在框架里添加按钮等部件需要先创建一个panel,作为其他部件的容器。一般创建一个和wx.Frame一样大小的wx.Panel实例,以容纳框架中的所有内容。如果框架内仅有一个子窗口,则该子窗口将自动调整大小,以覆盖整个框架,即便构建时指定了尺寸。可以通过tab按钮遍历wx.Panel中的元素,wx.Frame中则不能。在wxPython中,只需在创建子窗口时指定父窗口即可将其隐式增加到父对象中,而无需显式指定。

29. 子窗口的位置和大小可以由sizers对象来管理,以适应用户调整窗口大小时的布局调整问题。

30. 添加状态栏:statusBar = self.CreateStatusBar(),创建了一个wx.StatusBar类的实例,自动放置在框架的底部,宽度与框架相同,高度由操作系统决定;添加工具栏:toolbar = self.CreateToolBar(),自动放置在框架的顶部;创建菜单栏:menuBar = wx.MenuBar();给工具栏添加工具:toolbar.AddSimpleTool(wx.NewId(), p_w_picpaths.getNewBitmap(), ”New”, ”Long help for 'New'”),参数依次是是ID、位图、较短的帮助提示文本、较长的帮助文本信息,在状态栏中显示;显示工具栏:toolbar.Realize();创建菜单:menu1 = wx.Menu(); menuBar.Append(menu1, ”&Copy”, ”Copy in status bar”),参数依次为ID、菜单选项文本、当鼠标位于其上时在状态栏中显示的文本; 菜单中添加分割线:menu2.AppendSeparator();在框架上添加菜单栏:self.SetMenuBar(menuBar)。

31. 三种常用的对话框:a. 消息对话框;b. 文本输入对话框;c. 下拉菜单。此外wxPython还提供文件选择器、色彩选择器、进度对话框、打印设置和字体选择器。

32. 消息对话框。实现方法是利用wx.MessageDialog。用法:dlg = wx.MessageDialog(None, 'Is this the coolest thing ever!', 'MessageDialog', wx.YES_NO | wx.ICON_QUESTION); result = dlg.ShowModal(); dlg.Destroy()。即先创建一个wx.MessageDialog类实例,然后存储其结果,然后销毁该对话框。

33. wx.MessageDialog类的构建方法:wx.MessageDialog(parent, message, caption=”Message box”, style=wx.OK | wx.CANCEL, pos=wx.DefaultPosition),其中parent为对话框的父窗口,message代表对话框中显示的文本,caption代表对话框标题栏中的文本;style代表对话框中按钮的样色,pos代表对话框位置。

34. ShowModal()方法将对话框以模式框架的方式显示,这意味着在对话框关闭之前,应用程序中的别的窗口不能响应用户事件。ShowModal()方法的返回值是一个整数,对于wx.MessageDialog,返回值是下面常量之一: wx.ID_YES, wx.ID_NO, wx.ID_CANCEL, wx.ID_OK。

35. 文本输入对话框。借助类wx.TextEntryDialog,用法:dlg = wx.TextEntryDialog(None, ”Who is buried in Grant's tomb?”, 'A Question', 'Cary Grant') #其中参数依次代表父窗口,窗口里显示的文本,窗口标题栏的文本,输入区域中的默认文本; if dlg.ShowModal() == wx.ID_OK #ShowModal()方法返回所按下的按钮的ID,默认的按钮样式参数是是wx.OK | wx.CANCEL: response = dlg.GetValue() #GetValue()方法可以得到用户文本区域输入的值,相应地,有一个SetValue()方法让改变文本区域中的文本。

36. 下拉菜单。借助类wx.SingleChoiceDialog,用法:创建类实例、获取用户选中的选项。构建方法:dlg = wx.SingleChoiceDialog(None, 'What version of Python are you using?', 'Single Choice', ['1.5.2', '2.0', '2.1.3', '2.2', '2.3.1']),参数与文本输入对话框中的基本相同,其中最后的列表为各选项。获取用户选项:if dlg.ShowModal() == wx.ID_OK: response = dlg.GetStringSelection(),其中GetStringSelection()返回实际所选的字符串,也可以用GetSelection()方法返回用户选项的索引。

iii 在事件驱动环境中工作

37. 先明确一大堆概念,都是event字辈的。事件(event):应用程序的生命周期内发生的事情,它要求有响应;事件对象(event object):代表一个一个事件,其中包括了事件的数据等属性,是类wx.Event或其子类如wx.CommandEvent和wx.MouseEvent等的实例;事件类型(event type):wxPython分配给每个事件对象的一个整数ID,提供关于事件的更详细的信息,比如,是鼠标单击还是鼠标移动;事件源(event source):产生事件的wxPython对象,如按钮、菜单、列表框等;事件驱动(event-driven):一个程序结构,其大部分时间花在等待或响应事件上;事件队列(event queue):尚未处理的事件的列表;事件处理器(event handler):响应事件时所调用的函数或方法,也称作处理器函数或处理器方法;事件绑定器(event binder):一个封装了特定窗口部件,特定事件类型和相应的事件处理器的wxPython对象,事件处理器必须用事件绑定器登记(register)后才能得到调用;wx.EvtHandler:一个wxPython类,用于在特定类型、事件源和事件处理器之间创建绑定。

38. 事件驱动程序的工作机制:程序定期检查是否有任何请求响应事情发生。常用的事件通知方法是把事件传送到一个中心队列,由该队列触发相应事件的处理,另外可以使用轮询的方法,所有可能引发事件的事件由主过程定期逐个查询并询问是否有没有处理的事件。当事件发生时,基于事件的系统试着确定相关代码来处理该事件,如果有,相关代码被执行。原系统事件转换为wx.Event实例,然后使用wx.EvtHandler.ProcessEvent()方法将事件分派给适当的事件处理器代码。

39. 绑定器的关联:self.Bind(wx.EVT_BUTTON, self.OnClick, aButton),将之前定义的事件绑定器对象wx.EVT_BUTTON与对象aButton上的按钮单击事件与方法self.OnClick关联起来。Bind()方法属于类wx.EvtHandler,而wx.EvtHandler是所有可显示对象的父类。

40. 在wxPython中,大部分窗口部件在响应低级事件时都导致高级事件发生,高级事件的设计是为了方便聚焦于最要紧事件上,而不是逐个追踪鼠标单击事件。

41. 一些常用的wx.Event的子类:a. wx.CloseEvent:框架关闭时触发,类型包括常规框架关闭和系统关闭事件;b. wx.CommandEvent:与窗口部件的简单的各种交互都将触发这个事件,如按钮单击、菜单项选择、单选按钮选择等,这些交互有它各自的事件类型;c. wx.KeyEvent:按键事件,类型包括按下按键、释放按键和整个按键动作;d. wx.MouseEvent:鼠标事件,类型包括鼠标移动和鼠标敲击,包括单击和双击;e. wx.PaintEvent:当窗口的内容需要被重画时触发;f. wx.SizeEvent:当窗口的大小或布局改变时触发;g. wx.TimerEvent:可以由类wx.Timer创建,为定时事件。

42. 事件绑定器由类wx.PyEventBinder的实例组成。有定义好的,也可以自己创建。预定义的绑定器实例的名字均以wx.EVT_开头。需要注意的是,用个wx.Event实例的GetEventType()方法得到的事件类型的整型数值并非wx.EVT绑定器名字的值。

43. 在wxPython中,任何能够响应事件的对象都是wx.EvtHandler的子类。所有窗口对象都是wx.EvtHandler的子类,因些在wxPython应用程序中的每个窗口部件都能够响应事件。

44. 常用的使用wx.EvtHandler的方法是用Bind()创建事件绑定,用法:Bind(event, handler, source=None, id=wx.ID_ANY, id2=wx.ID_ANY),其中source用于在窗口中存在多个事件源时声明事件源,或者标识某项目,即使它不是事件源。

45. 常用的wx.EvtHandler的方法:a. AddPendingEvent(event):将这个event参数放入事件处理系统中,适用于线程间的基于事件的通信;b. GetEvtHandlerEnabled():如果处理器当前正在处理事件,则属性为True,否则为False,此外还有相应的SetEvtHandlerEnabled();c. ProcessEvent(event):把event对象放入事件处理系统中以便立即处理;d. Bind(),略。

46. 事件处理过程的机制:流程开始于触发事件的对象,之后一般首先在触发对象中查找与事件类型的绑定处理器函数。找到则执行相应处理器。如果没有找到,wxPython将检查该事件是否传送到了上一级的容器。如果是则检查父窗口的部件,这样逐级向上寻找,直到wxPython找到处理器或者到达了顶级窗口。如果事件没有传播,在处理过程完成之前,wxPython仍将为了处理器函数而检查应用程序对象。此外当事件处理器运行时,过程通常就结束了,不过函数可以告诉wxPython继续去查找处理器。

47. 在图形界面上disable窗口部件:使用wx.Window的Disable()和Enable()方法。

48. 对于初始对象有效或无效状态的检查,这发生在ProcessEvent()方法中,它是类wx.EvtHandler中的方法。如果ProcessEvent()方法最后完成了事件处理,则ProcessEvent()返回True。处理器函数还可以通过调用wx.Event的Skip()方法来显式地请求进一步的处理即寻找绑定器对象。Skip()方法在处理中的任一点或处理器所调用的任何代码中都可以被调用。Skip()方法在事件实例中设置一个标记,在事件处理器方法完成后,wxPython检查这个标记。

49. 默认情况,只有wx.CommandEvent及其子类的实例向上展开(propagate)至容器水平,其它事件不展开。在wx.Button上敲击鼠标产生的事件wx.EVT_BUTTON属于wx.CommandEvent子类,而鼠标事件不是wx.CommandEvent的子类。

50. 窗口系统类型事件只对窗口部件感兴趣,而应用级事件则对应容器级。这个规则并不防碍我们在任何水平声明绑定,而无论绑定的对象和事件管理器的类型。低级的非命令事件通常用于窗口部件或系统水平的通知,如鼠标敲击、按键按下、绘画请求、调整大小或移动,而命令事件,如在按钮上敲击鼠标、或列表框上的选择等,通常由窗口部件自己生成。

51. 最后,如果遍历了容器水平而仍然没有找到绑定,那么应用程序的wx.App对象调用ProcessEvent()。默认没有行为,但是可以给wx.App增加事件绑定,这样就以非标准的方式来传递事件。

52. Skip()方法可以用于实现同一事件的多个反应,在定义方法时用到,记得是在低级事件如鼠标事件的

53. 一些修改主循环的wx.App方法:a. Dispatch():强制发送事件队列中的下一个事件至主循环;b. Pending():检查事件队列中是否有等待被处理的事件,有则返回True;c. Yield(onlyIfNeeded=False):允许分配等候处理事件,否则将锁定窗口系统,不能显示或更新,如果等候处理的事件已被处理则返回True,其中如果onlyIfNeeded参数为True,则当前的处理让位于等候处理的事件,另有全局函数wx.SafeYield(),可阻止用户在Yield期间输入数据(通过使用来输入的窗口部件临时无效),以免干扰Yield操作。

54. 另一种管理主循环的方法是创建自己的事件类型来匹配应用程序中特定的数据和窗口部件。创建自定义事件的步骤:a. 定义一个新的事件类,为wxPython的wx.PyEvent类的子类,如果此事件为命令事件,则可以创建一个wx.PyCommandEvent的子类;b. 创建事件类型和绑定器对象以绑定该事件;c. 添加事件实例的代码,用ProcessEvent()方法将这个实例引入事件处理系统,此后的创建绑定和处理器方法与wxPython提供的事件做法一样。

55. 创建事件类型:myEVT_TWO_BUTTON = wx.NewEventType()。

56. 创建绑定器对象:EVT_TWO_BUTTON = wx.PyEventBinder(myEVT_TWO_BUTTON, 1)。

57. 创建自定义事件:evt = TwoButtonEvent(myEVT_TWO_BUTTON, self.GetId())。wx.PyEvent和wx.PyCommandEvent是wxPython特定的结构,可以用它们创建新的事件类并与C++类连接起来。不能直接使用wx.Event创建新方法,因为C++事件处理不了解该Python子类。

58. 处理事件:self.GetEventHandler().ProcessEvent(evt),其中evt是事件,self属于类Panel。

iv 用PyCrust使得wxPython更易处理

59. PyCrust中的命令重调用快捷键:a. Ctrl+上箭头:获取前一个历史项;b. Ctrl+下箭头:获取下一个历史项;c. Alt+p:获取前一个历史项;d. Alt+n:获取下一个历史项;e. Shift+上箭头:插入前一个历史项;f. Shift+下箭头:插入下一个历史项;g. F8:历史项命令补全(键入先前命令的少量字符并按F8);h. Ctrl+Enter:在多行命令中插入新行。

60. 复制粘帖编辑的快捷键:a. Ctrl+c:复制所选的文本,不带提示符;b. Ctrl+Shift+c:复制所选的文本,保留提示符;c. Ctrl+Shift+v:粘贴自剪贴板的多个命令并运行。

61. PyCrust的标签,F4切换显示:a. Namespace;b. Display,用于展示对象;c. Calltip(调用提示),显示最近一次调用的函数或方法的用法(tips for calling);d. History,列出当前shell会话中所键入的所有命令;e. Dispatcher,提供在应用程序中联系对象的机制,PyCrust使用dispatcher来维持界面的更新。

62. 使用pywrap可将脚本在PyCrust中分析,使用时需进入脚本所在目录下。

v 创建你的蓝图

63. 代码重构的目的:保持代码在以后易于阅读和维护。进行重构时的一些原则:a. 不要重复:避免多段代码行使相同功能,否则维护起来很麻烦;b. 一次做一件事情:一个方法应该并且只做一件事情,各自的事件应该在各自的方法中,方法应该保持短小;c. 嵌套的层数要少:尽量使嵌套代码不多于3层;d. 避免字面意义上的字符串和数字:可以把它们从代码的主要部分中分离出来,存在列表或字典中。

64. MVC(Model-View-Controller)系统。有三个子系统:a. 模型(Model)包含经常被调用的业务逻辑或数据和信息,包括一个针对外部存储的接口,通常只有一个API接口;b. 视图(View)包含显示数据的对象即显示代码,wxPython中,wx.Window水平的所有的对象都属于视图子系统;c. 管理器(Controller)管理与用户的交互,作为Model和View的桥梁,包含交互逻辑,此子系统对应wxPython中的wx.EvtHandler水平。

65. 在现代的UI工具包中,View和Controller集成在一起,在wxPython中,这一点表现为所有的wx.Window对象也都是wx.EvtHandler的子类。

66. MVC体系的工作机制:事件首先来到管理器系统,后者受理之,将事件处理器分配到模型系统,处理完成后,模型将更新后的数据发送回管理器;另一方面,管理器发送更新通知到视图系统,后者显示更新后的界面。一个成功的MVC设计的关键不在于每个对象都彼此了解。相反,一个成功的MVC程序,它的不同部分之间显式地隐藏了一些东西。其目的是使系统最低限度地交互,和方法之间的明确的界定。模型组分应该从视图和管理器中完全脱离出来,而可以做到能不改变模型而只改变其他两个系统系统。理想上来讲,更进一步,甚至应该能够使用同一个模型来驱动非wxPython的界面。从视图系统来看,也应该能够实现不改变视图和管理器的前提下修改模型,其做法是创建一个抽象的模型类,它定义视图系统可以使用的API。

67. 自定义模型:首先构造数据类,不用考虑如何显示它们;然后为数据类作一个公共接口,该接口对显示对象是能访问到的。

68. wxPython提供类AbstractModel,它是object的一个子类,用时需import abstractmodel(2.6/2.8中显示没有此模块,原因未知)。

69. 另外,wxPython包含两个单独的类似MVC更新机制的实现,分别是wx.lib.pubsub和wx.lib.evtmgr.eventManager模块,有更多比AbstractModel类的功能。

70. 单元测试:对程序的单个的特定功能的测试。

71. 测试界面本身的功能比较困难,因为界面的行为依赖于用户的行为,而用户的行为又是难以封装的。可以使用已有的测试框架unittest模块以减少工作量,该模块使用PyUnit测试框架,后者由Test,TestCase,TestSuite组成。

72. Test:被PyUnit引擎调用的一个单独的方法。根据约定,测试方法的名字以test开头。测试方法通常执行一些代码,然后执行一或多个断定语句来测试结果是否符合预期。

73. TestCase:一个类,定义了一个或多个单独的测试,这些测试共享一个公共的配置。TestCase对每个测试都在测试前后提供公共配置支持,确保每个测试分别运行。TestCase中还定义了一些专门的断定方法,如assertEqual。

74. TestSuite:为同时执行而组合在一起的一个或多个test方法或TestCase对象。

75. 单个的PyUnit测试可能有三种结果:success(成功), failure(失败), 或error(错误)。测试中一旦出现failure或error即终止整个测试,然后执行下一个单个的测试。

76. 在每个测试执行前调用SetUp()方法,以保证每个应用程序的测试都在相同的状态下进行。同样地,在每个测试执行完之后都调用TearDown()方法,完成一些清理工作,以确保测试之间系统状态的一致。

77. makeSuite()方法要求一个Python类对象和一个字符串前缀作为参数,并返回一组测试(包含该类中所有前缀为方法中前缀参数值的方法)。

78. 调用测试方法:unittest.main(defaultTest='suite') ,这里使用了PyUnit的基于文本的执行器,其中的参数是一个方法的名字(即一组测试的那个方法),测试结果输出到控制台。如果想使用GUI测试执行器,则unittest.TextTestRunner方法。

vi 使用基本的建造部件

79.要在屏幕上绘画,我们要用到一个名为device context(设备环境)的wxPython对象。设备环境代表抽象的设备,使用类wx.DC及其子类来代表。由于wx.DC是抽象的,所以对于应用程序来说,需要使用其子类。设备环境应该是局部、临时性的,不应该以实例变量、全局变量等形式在方法调用之间保留。在某些平台上,设备环境是有限的资源,长期持有wx.DC可能导致程序不稳定。

80. wx.DC的子类:a. wx.BufferedDC:用于缓存一套绘画命令,直到命令完整并准备在屏幕上绘画;b. wx.BufferedPaintDC:和wx.BufferedDC一样,但是仅用于单个wx.PaintEvent的处理中,仅临时创建该类的实例;c. wx.ClientDC:用于在窗口对象上绘画,仅适用于wx.PaintEvent以外的处理;d. wx.MemoryDC:用于绘制图形到内存中的一个位图中,可以在之后用wx.DC.Blit()方法来将此位图绘制到窗口中;e. wx.MetafileDC:用来在win下创建标准窗口图元文件数据;f. wx.PaintDC:等同于wx.ClientDC,仅用于单个wx.PaintEvent的处理中,仅临时创建该类的实例;g. wx.PostScriptDC:用于写压缩的PostScript文件;h. wx.PrinterDC:用于在win下写到打印机;i. wx.ScreenDC:用于在窗口的顶部或外部,即直接在屏幕上绘画,该类应该只临时创建;j. wx.WindowDC:用于在窗口对象的整个区域上绘画,包括边框以及非客户区域,非Windows系统可能不支持该类。

81. 创建wx.Pen对象:self.pen = wx.Pen(self.color, self.thickness, wx.SOLID),其中self为wx.Window子类,样式除了wx.SOLID还有wx.DOT, wx.LONGDASH, 和wx.SHORTDASH。

82. 创建缓存的设备环境:self.buffer = wx.EmptyBitmap(size.width, size.height; dc = wx.BufferedDC(None, self.buffer),使用设备环境:self.DrawLines(dc),self.drawMotion(dc, event)。

83. 获取鼠标位置:事件方法GetPositionTuple()。

84. CaptureMouse()方法控制了鼠标并在窗口的内部捕获鼠标,即使将鼠标拖动到窗口边框的外面,它仍然只响应窗口内的鼠标动作。在程序的后面必须调用ReleaseMouse()来取消其对鼠标的控制。否则该窗口将无法通过鼠标关闭等。wxPython应用程序使用椎栈来对捕获鼠标的窗口进行跟踪,调用ReleaseMouse()相当于从椎栈中弹出。

85. 缓存的好处。比如由两个特定wx.DC子类实现绘画的缓存,其中一个绘画缓存是一个不显现的区域,其中存储了所有的绘画命令,这些命令能够一起执行,并且一步到位地复制到屏幕上。缓存的好处是用户看不到单个绘画命令的发生,因此屏幕不会闪烁。

86. wxPython中有两个用于缓存的类:wx.BufferDC(通常用于缓存wx.ClientDC)、wx.BufferPaintDC(用于缓存wx.PaintDC)。它们工作方式基本上一样。缓存设备环境的创建要使用两个参数,分别是适当类型的目标设备环境和wx.Bitmap对象。当绘画命令作用到缓存的设备环境时,使用一个内在的wx.MemoryDC进行位图绘制。缓存对象的销毁通常发生在对象退出作用域时,此时,C++销毁器使用Blit()方法去自动复制位图到目标。

87. 一些wx.DC方法。a. Blit(xdest, ydest, width, height, source, xsrc,ysrc):从源设备环境将块复制到调用该方法的设备环境,参数依次代表复制到目标上下文的起始点、要复制的区域的宽度和高度、源设备环境和源设备环境中的复制起点;b. Clear():通过使用当前的背景刷来清理设备环境;c. DrawArc(x1, y1, x2, y2, xc, yc):使用起点(x1, y1)和终点(x2, y2)画一个圆弧,(xc, yc)是圆弧的中心,用当前的画刷填充,逆时针绘制,还有绘制椭圆圆弧的DrawEllipticalArc();d. DrawCircle(x, y, radius) DrawCircle(point, radius),DrawIcon(icon, x, y),DrawLine(x1, y1, x2, y2),DrawPolygon(points),DrawRectangle(x, y,width, height),DrawText(text, x, y),GetFont() SetFont(font);e. FloodFill(x, y, color,style),GetPen() SetPen(pen),GetPixel(x, y),GetSize() GetSizeTuple();f. GetBackground() SetBackground(brush),GetBrush() SetBrush(brush)。还有一些方法,见Chap xii。

88. 自定义状态栏:使用SetStatusBar()方法,并以该类的实例作为参数以将状态栏附着到框架上。状态栏上显示单一的一段文本:使用wx.StatusBar的SetStatusText()方法。想要在状态栏中显示多个文本元素的话,可以用SetFieldsCount()方法在状态栏中创建多个文本域。调整文本域的尺寸:SetStatusWidth()方法。

89. StatusBar使用堆栈存储状态域,可用PushStatusText()和PopStatusText()方法在临时显示新的文本之后返回先前的状态文本。

90. wx.StatusBar类最常用的方法。a. GetFieldsCount() SetFieldsCount(count):得到或设置状态栏中域的数量;b. GetStatusText(field=0) SetStatusText(text, field=0):得到或设置指定域中的文本。0是默认值,代表最左端的域;c. PopStatusText(field=0):弹出堆栈中的文本到指定域中,以改变域中的文本为弹出;d. PushStatusText(text, field=0):改变指定的域中的文本为给定的文本,并将改变前的文本压入堆栈的顶部;e. SetStatusWidths(widths):指定各状态域的宽度,widths为元素为整型的列表。

91. wx.ToolBar类的样式:a. wx.TB_3DBUTTONS:3D外观;b. wx.TB_HORIZONTAL:默认样式,工具栏水平布置;c. wx.TB_NOICONS:不为每个工具显示位图;d. wx.TB_TEXT:根据不同的位图显示简短的帮助文本;e. wx.TB_VERTICAL:垂直放置工具栏。

92. wx.ToolBar的常用方法:a. AddControl(control):添加wxPython控件,相关方法InsertControl();b. AddSeparator():在工具之间放置空格;c. AddSimpleTool(id, bitmap,shortHelpString="",kind=wx.ITEM_NORMAL):添加一个简单的带有给定位图的工具到工具栏,shortHelpString作为提示显示,kind的值可以是wx.ITEM_NORMAL, wx.ITEM_CHECKBOX, 或wx.ITEM_RADIO;d. AddTool(id, bitmap,bitmap2=wx.NullBitmap,kind=wx.ITEM_NORMAL,shortHelpString="",longHelpString="", clientData=None):添加工具,bitmap2是当该工具被按下时所显示的位图,longHelpString是当指针位于该工具中时显示在状态栏中的帮助字符串,clientData用于将任意的一块数据与工具相联系起来,相关方法InsertTool();e. AddCheckTool(...):添加一个复选框切换工具,所要求参数同AddTool();f. AddRadioTool(...):添加一个单选切换工具,所要求参数同AddTool(),对于连续的未分隔的单选工具被视为一组;g. DeleteTool(toolId) DeleteToolByPosition(x, y):删除所给定的id的工具,或删除给定显示位置的工具;h. FindControl(toolId) FindToolForPosition(x, y):查找并返回给定id或显示位置的工具;i. ToggleTool(toolId, toggle):切换给定id的工具的状态。

93. 标准文件对话框:wx.FileDialog类。构造器:wx.FileDialog(parent, message="Choose a file", defaultDir="", defaultFile="", wildcard="*.*", style=0),其中parent代表对话框的父窗口,没有则为None;message为对话框的标题栏的文本,defaultDir为当对话框打开时的默认目录,如果为空则为当前工作目录;defaultFile,默认文件;wildcard代表通配符,指定要选择的文件类型,如:Sketch files (*.sketch)|*.sketch|All files (*.*)|*.*;style:样式,包括wx.CHANGE_DIR(用户选择文件之后,当前工作目录相应改变到所选文件所在的目录),wx.MULTIPLE(仅适用于打开对话框,这样可以选择多个文件),wx.OPEN(打开文件),wx.OVERWRITE_PROMPT(提示确认是否覆盖已存在的文件),wx.SAVE(保存文件)。

94. 使用文件对话框需要对话框实例调用ShowModal()方法,该方法返回wx.ID_OK或wx.ID_CANCEL。获取数据需要使用GetFilename(), GetDirectory(), 或GetPath()方法。最后,调用Destroy()销毁对话框。

95. 颜色选择器:wx.ColourDialog。其构造和用法类似于文件对话框。构造器的参数为parent和可选的数据属性参数,后者为wx.ColourData类实例,存储与该对话框相关的一些数据,如用户选择的颜色和自定义颜色的列表(用于保持自定义颜色的一致性)。

96. wxPython使用sizer作为布局机制,类似于Java AWT和其它的界面工具包中的布局管理器。每个容器窗口都有sizer,父窗口中创建的子部件必须被添加给sizer以管理其尺寸和位置。

97. 创建和使用sizer的步骤:a. 创建panel或其他容器;b. 创建sizer;c. 创建子窗口;d. 使用sizer的Add()方法,将每个子窗口添加给sizer,sizer允许嵌套,可以预留一定数量的空间作为分隔;e. 调用容器的SetSizer(sizer)方法。

98. 常用的wxsizer。a. wx.BoxSizer:在一条线上布局子窗口部件,布局方向可以水平或竖直,并且可以包含,在项目被添加时传递给sizer的参数控制子窗口部件如何根据box的主体或垂直轴线作相应的尺寸调整;b. wx.StaticBoxSizer:wx.BoxSizer周边附加一个边框,其标签可选;c. wx.GridSizer:一个固定的二维网格,每个元素都有相同的尺寸,行和列其中一个数量固定,从左至右添加项;d. wx.FlexGridSizer:固定的二维网格,与wx.GridSizer的区别在于行和列已根据所在行或列的最大元素设置好了;e. wx.GridBagSizer:固定的二维网格,基于wx.FlexGridSizer,允许特定项放置在网格上的特定点以及项目跨越网格区域。

99. 常用wx.Sizer方法:a. Add(size, proportion=0,flag=0, border=0,userData=None),参数proportion管理窗口总尺寸,flag是一个位图,针对对齐、边框位置,增长有许多不同的标志,border代表窗口或sizer边缘的像素,userData用于数据关联;b. Fit(window):调整window尺寸以匹配sizer认为所需要的最小化尺寸;c.FitInside:Fit的内部实现,用于scroll panel中的窗口以触发滚动栏的显示;d. GetSize():以wx.Size对象的形式返回sizer的尺寸;e. GetPosition():以wx.Point对象的形式返回sizer的位置;f. GetMinSize():以wx.Size对象的形式返回完全填充sizer所需的最小尺寸;g. Layout():强制sizer重新计算其子部件的尺寸和位置,可在动态地添加或删除子部件之后调用;h. Prepend(...):与Add()相同,不过把新的对象放在sizer列表的开头;i. Remove(window) Remove(sizer) Remove(nth):从sizer中删除一个对象;j. SetDimension(x, y, width,height):强制sizer按照给定的参数重新定位子部件。

100. About框的构建:可以借助类wx.html.HtmlWindow。

101. 启动画面:使用类wx.SplashScreen。一般在应用程序启动期间的OnInit方法中声明。构造方法:wx.SplashScreen(bitmap, splashStyle, milliseconds, parent, id, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.SIMPLE_BORDER|wx.FRAME_NO_TASKBAR|wx.STAY_ON_TOP),其中splashStyle代表位图样式,可以是下列的结合:wx.SPLASH_CENTRE_ON_PARENT,wx.SPLASH_CENTRE_ON_SCREEN, wx.SPLASH_NO_CENTRE, wx.SPLASH_TIMEOUT, wx.SPLASH_NO_TIMEOUT,milliseconds为wx.SPLASH_TIMEOUT样式中启动画面停留的时间。实现启动画面显示ield()的调用很重要,它使得启动画面在应用程序继续启动前能够接受并处理其初始化绘制事件。