注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

风雨启示录

欢迎光临我的网店优优我心:http://uumyheart.taobao.com

 
 
 

日志

 
 

wxPython in Action (三)  

2008-07-26 15:16:41|  分类: python学习笔记 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |


2.4.1 管理正常的关闭

在关闭的过程期间, wxPython关心的是删除所有的它的窗口和释放它们的资源。你可以在退出过程中定义一个钩子来执行你自己的清理工作。由于你的wx.App子类的 OnExit()方法在最后一个窗口被关闭后且在wxPython的内在的清理过程之前被调用,你可以使用OnExit()方法来清理你创建的任何非 wxPython资源(例如一个数据库连接)。即使使用了wx.Exit()来关闭wxPython程序,OnExit()方法仍将被触发。

如 果由于某种原因你想在最后的窗口被关闭后wxPython应用程序仍然可以继续,你可以使用wx.App的SetExitOnFrameDelete (flag)方法来改变默认的行为。如果flag参数设置为False,那么最后的窗口被关闭后wxPython应用程序仍然会继续运行。这意味着 wx.App实例将继续存活,并且事件循环将继续处理事件,比如这时你还可以创建所有新的这里所谓的顶级窗口。wxPython应用程序将保持存活直到全 局函数wx.Exit()被明确地调用。


2.4.2 管理紧急关闭

你不能总是以一个可控的方法关闭你的程序。有时候,你需要立即结束应用程序并不考虑清理工作。例如一个必不可少的资源可能已被关闭或被损坏。如果系统正在关闭,你可能不能做所有的清理工作。

这 里有两种在紧急情况下退出你的wxPython应用程序的方法。你可以调用wx.App的ExitMainLoop()方法。这个方法显式地使用主消息循 环终止,使用控制离开MainLoop()函数。这通常将终止应用程序,这个方法实际上等同于关闭所有这里所谓顶级窗口。

你也可以调用全局方法wx.Exit()。正常使用情况下,两种方法我们都不推荐,因为它将导致一些清理函数被跳过。

有 时候,你的应用程序由于一个控制之外的事件而需要关闭。例如操作系统的关闭或注销。在这种情况下,你的应用程序将试图做一些保存文档或关闭连接等等。如果 你的应用程序为wx.EVT_QUERY_END_SESSION事件绑定了一个事件处理器,那么当wxPython得到关闭通知时这个事件处理器将被调 用。这个event参数是wx.CloseEvent。我们可以通过关闭事件来否决关闭。这可以使用关闭事件的CanVeto()方法,CanVeto ()方法决定是否可以否决,Veto()执行否决。如果你不能成功地保存或关闭所有的资源,你可能想使用该方法。 wx.EVT_QUERY_END_SESSION事件的默认处理器调用顶级窗口的Close()方法,这将依次向顶层窗口发送wx.EVT_CLOSE 事件,这给了你控制关闭过程的另一选择。如果任何一个Close()方法返回False,那么应用程序将试图否决关闭。


2.5 如何创建和使用顶级窗口对象?

在你的应用程序中一个顶级窗口对象是一个窗口部件(通常是一个框架),它不被别的窗口部件所包含。顶级窗口对象通常是你的应用程序的主窗口,它包含用户与之交互的窗口部件和界面对象。当所有的顶级窗口被关闭时应用程序退出。

你 的应用程序至少必须有一个顶级窗口对象。顶级窗口对象通常是类wx.Frame的子类,尽管它也可以是wx.Dialog的子类。大多数情况下,你将为了 使用为你的应用程序定义定制的wx.Frame的子类。然而,这儿也存在一定数量的预定义的wx.Dialog的子类,它们提供了许多你可能会在一个应用 程序中遇到的典型的对话框。

这儿可能有一个名称上的混淆,那就是“顶级窗口”。一般意义上的顶级窗口是指在你的应用程序中任何没有父容器 的窗口部件。你的应用程序必须至少有一个,但是,只要你喜欢可以有多个。但是它们中只有一个可以通过使用SetTopWindow()被wxPython 作为主顶级窗口。如果你没有使用SetTopWindow()指定主顶级窗口,那么在wx.App的顶级窗口列表中的第一个框架将被认为是这个主顶级窗 口。因此,明确地定义一个主顶级窗口不总是必要的,例如,你只有一个顶级窗口的时候。反复调用SetTopWindow()将反复改变当前的主顶级窗口, 因为一个应用程序一次只能有一主顶级窗口。


2.5.1 使用wx.Frame

按照 wxPython中的说法,框架就是用户通常称的窗口。那就是说,框架是一个容器,用户可以将它在屏幕上任意移动,并可将它缩放,它通常包含诸如标题栏、 菜单等等。在wxPython中,wx.Frame是所有框架的父类。这里也有少数专用的wx.Frame子类,你可以使用它们。

当你创建wx.Frame的子类时,你的类应该调用其父类的构造器wx.Frame.__init__()。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。

title:窗口的标题。

pos:一个wx.Point对象,它指定这个新窗口的左上角在屏幕中的位置。在图形用户界面程序中,通常(0,0)是显示器的左上角。这个默认的(-1,-1)将让系统决定窗口的位置。

size:一个wx.Size对象,它指定这个窗口的初始尺寸。这个默认的(-1,-1)将让系统决定窗口的初始尺寸。

style:指定窗口的类型的常量。你可以使用或运算来组合它们。

name:框架的内在的名字。以后你可以使用它来寻找这个窗口。

记住,这些参数将被传递给父类的构造器方法:wx.Frame.__init__()。

创建wx.Frame子类的方法如下所示:

class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, "My Friendly Window",
            (100, 100), (100, 100))


2.5.2 使用wxPython的ID

在wxPython 中,ID号是所有窗口部件的特征。在一个wxPython应用程序中,每个窗口部件都有一个窗口标识。在每一个框架内,ID号必须是唯一的,但是在框架之 间你可以重用ID号。然而,我们建议你在你的整个应用程序中保持ID号的唯一性,以防止处理事件时产生错误和混淆。在wxPython中也有一些标准的预 定义的ID号,它们有特定的意思(例如,wx.ID_OK和wx.ID_CANCEL是对话框中的OK和Cancel按钮的ID号)。在你的应用程序中重 用标准的ID号一般没什么问题,只要你在预期的方式中使用它们。在wxPython中,ID号的最重要的用处是在指定的对象发生的事件和响应该事件的回调 函数之间建立唯一的关联。

有三种方法来创建一个窗口部件使用的ID号:

1、明确地给构造器传递一个正的整数
2、使用wx.NewId()函数
3、传递一个全局常量wx.ID_ANY或-1给窗口部件的构造器

明确地选择ID号

第 一个或最直接的方法是明确地给构造器传递一个正的整数作为该窗口部件的ID。如果你这样做了,你必须确保在一个框架内没有重复的ID或重用了一个预定义的 常量。你可以通过调用wx.RegisterId()来确保在应用程序中wxPython不在别处使用你的ID。要防止你的程序使用相同的 wxPython ID,你应该避免使用全局常量wx.ID_LOWEST和wx.ID_HIGHEST之间的ID号。

使用全局性的NewID()函数

自己确保ID号的唯一性十分麻烦,你可以使用wx.NewId()函数让wxPython来为你创建ID:

id = wx.NewId()
frame = wx.Frame.__init__(None, id)

你也可以给窗口部件的构造器传递全局常量wx.ID_ANY或-1,然后wxPython将为你生成新的ID。然后你可以在需要这个ID时使用GetId()方法来得到它:

frame = wx.Frame.__init__(None, -1)
id = frame.GetId()


2.5.3 使用wx.Size和wx.Point

wx.Frame构造器的参数也引用了类wx.Size和wx.Point。这两个类在你的wxPython编程中将频繁被使用。
wx.Point类表示一个点或位置。构造器要求点的x和y值。如果不设置x,y值,则值默认为0。我们可以使用Set(x,y)和Get()函数来设置和得到x和y值。Get()函数返回一个元组。x和y值可以像下面这样作为属性被访问:

point = wx.Point(10, 12)
x = point.x
y = point.y

另外,wx.Point的实例可以像其它Python对象一样作加、减和比较运算,例如:

a = wx.Point(2, 3)
b = wx.Point(5, 7)
c = a + b
bigger = a > b

在wx.Point的实参中,坐标值一般为整数。如果你需要浮点数坐标,你可以使用类wx.RealPoint,它的用法如同wx.Point。

wx.Size类几乎和wx.Point完全相同,除了实参的名字是width和height。对wx.Size的操作与wx.Point一样。

在你的应用程序中当一个wx.Point或wx.Size实例被要求的时候(例如在另一个对象的构造器中),你不必显式地创建这个实例。你可以传递一个元组给构造器,wxPython将隐含地创建这个wx.Point或wx.Size实例:

frame = wx.Frame(None, -1, pos=(10, 10), size=(100, 100))


2.5.4 使用wx.Frame的样式

每 个wxPython窗口部件都要求一个样式参数。这部分我们将讨论用于wx.Frame的样式。它们中的一些也适用于别的wxPython窗口部件。一些 窗口部件也定义了一个SetStyle()方法,让你可以在该窗口部件创建后改变它的样式。所有的你能使用的样式元素都有一个常量标识符(如 wx.MINIMIZE_BOX)。要使用多个样式,你可以使用或运算符|。例如,wx.DEFAULT_FRAME_STYLE样式就被定义为如下几个 基本样式的组合:

wx.MAXIMIZE_BOX | wx.MINIMIZE_BOX | wx.RESIZE_BORDER |
wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX

要从一个合成的样式中去掉个别的样式,你可以使用^操作符。例如要创建一个默认样式的窗口,但要求用户不能缩放和改变窗口的尺寸,你可以这样做:

wx.DEFAULT_FRAME_STYLE ^ (wx.RESIZE_BORDER | wx.MINIMIZE_BOX |wx.MAXIMIZE_BOX)

如果你不慎使用了&操作符,那么将得到一个没有样式的、无边框图的、不能移动、不能改变尺寸和不能关闭的帧。

下表2.2列出了用于wx.Frame的最重要的样式:

wx.CAPTION:在框架上增加一个标题栏,它显示该框架的标题属性。
wx.CLOSE_BOX:指示系统在框架的标题栏上显示一个关闭框,使用系统默认的位置和样式。
wx.DEFAULT_FRAME_STYLE:默认样式。
wx.FRAME_SHAPED:用这个样式创建的框架可以使用SetShape()方法去创建一个非矩形的窗口。
wx.FRAME_TOOL_WINDOW:通过给框架一个比正常更小的标题栏,使框架看起来像一个工具框窗口。在Windows下,使用这个样式创建的框架不会出现在显示所有打开窗口的任务栏上。
wx.MAXIMIZE_BOX:指示系统在框架的标题栏上显示一个最大化框,使用系统默认的位置和样式。
wx.MINIMIZE_BOX:指示系统在框架的标题栏上显示一个最小化框,使用系统默认的位置和样式。
wx.RESIZE_BORDER:给框架增加一个可以改变尺寸的边框。
wx.SIMPLE_BORDER:没有装饰的边框。不能工作在所有平台上。
wx.SYSTEM_MENU:增加系统菜单(带有关闭、移动、改变尺寸等功能)和关闭框到这个窗口。在系统菜单中的改变尺寸和关闭功能的有效性依赖于wx.MAXIMIZE_BOX, wx.MINIMIZE_BOX和wx.CLOSE_BOX样式是否被应用。

下面的四张图显示了几个通常的框架的样式。

图2.4是使用wx.DEFAULT_STYLE创建的。
图2.5是使用wx.DEFAULT_FRAME_STYLE ^ (wx.RESIZE_BORDER | wx.MINIMIZE_BOX |wx.MAXIMIZE_BOX)组合样式创建的。
图2.6使用的样式是wx.DEFAULT_FRAME_STYLE | wx.FRAME_TOOL_WINDOW。
图2.7使用了扩展样式 wx.help.FRAME_EX_CONTEXTHELP。


2.6 如何为一个框架增加对象和子窗口?

我们已经说明了如何创建wx.Frame对象,但是创建后的是空的。本节我们将介绍在你的框架中插入对象与子窗口的基础,以便与用户交互。


2.6.1 给框架增加窗口部件

图2.8显示了一个定制的wx.Frame的子类,名为InsertFrame。当点击close按钮时,这个窗口将关闭且应用程序将退出。例2.3定义了子类InsertFrame。

例2.3

#!/usr/bin/env python

import wx

class InsertFrame(wx.Frame):

    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id, 'Frame With Button',
                size=(300, 100))
        panel = wx.Panel(self) #创建画板  
        button = wx.Button(panel, label="Close", pos=(125, 10),
                size=(50, 50)) #将按钮添加到画板
    #绑定按钮的单击事件
        self.Bind(wx.EVT_BUTTON, self.OnCloseMe, button)
    #绑定窗口的关闭事件
        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) 

    def OnCloseMe(self, event): 
        self.Close(True)

    def OnCloseWindow(self, event):
        self.Destroy()

if __name__ == '__main__':
    app = wx.PySimpleApp()
    frame = InsertFrame(parent=None, id=-1)
    frame.Show()
    app.MainLoop()

类InsertFrame 的方法__init__创建了两子窗口。第一个是wx.Panel,它是其它窗口的容器,它自身也有一点功能。第二个是wx.Button,它是一个平常 按钮。接下来,按钮的单击事件和窗口的关闭事件被绑定到了相应的函数,当事件发生时这相应的函数将被调用执行。

大多数情况下,你将创建一个与你的wx.Frame大小一样的wx.Panel实例以容纳你的框架上的所有的内容。这样做可以让定制的窗口内容与其他如工具栏和状态栏分开。 通过tab按钮,可以遍历wx.Panel中的元素,wx.Frame不能。

你不必像使用别的UI工具包那样,你不需要显式调用一个增加方法来向双亲中插入一个子窗口。在wxPython中,你只需在子窗口被创建时指定父窗口,这个子窗口就隐式地增加到父对象中了,例如例2.3所示。

你 可能想知道在例2.3中,为什么wx.Button被创建时使用了明确的位置和尺寸,而wx.Panel没有。在wxPython中,如果只有一个子窗口 的框架被创建,那么那个子窗口(例2.3中是wx.Panel)被自动重新调整尺寸去填满该框架的客户区域。这个自动调整尺寸将覆盖关于这个子窗口的任何 位置和尺寸信息,尽管关于子窗口的信息已被指定,这些信息将被忽略。这个自动调整尺寸仅适用于框架内或对话框内的只有唯一元素的情况。这里按钮是 panel的元素,而不是框架的,所以要使用指定的尺寸和位置。如果没有为这个按钮指定尺寸和位置,它将使用默认的位置(panel的左上角)和基于按钮 标签的长度的尺寸。

显式地指定所有子窗口的位置和尺寸是十分乏味的。更重要的是,当用户调整窗口大小的时候,这使得子窗口的位置和大小不能作相应调整。为了解决这两个问题,wxPython使用了称为sizers的对象来管理子窗口的复杂布局。
  评论这张
 
阅读(1086)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017