wxPython事件



事件是每一个GUI应用程序的组成部分。所有的GUI应用程序是事件驱动的。应用程序反应,以产生不同的事件,在其生命周期类型。事件的产生主要是由应用程序的用户。但它们可以产生,以及通过其他手段。例如互联网连接,窗口管理器,定时器。所以,当我们调用mainloop()方法,等待我们的应用程序产生事件。 mainloop()方法结束时退出应用程序。
定义
事件是一个从底层框架,通常的GUI工具包的应用程序级信息的一块。事件循环是一种编程构造和调度事件或程序中的消息等待。事件循环反复查找进程的事件。调度程序是一个过程,映射事件到事件处理程序。事件处理程序,对事件作出反应的方法。
事件对象是与事件相关联的对象。它通常是一个窗口。事件类型是一个已产生的独特的事件。事件绑定是一个对象,结合事件处理程序的事件类型。
一个简单的例子
这个例子里面讨论move事件。类型是wx.Movie的事件。此事件绑定是wx.EVT_MOTION。
[python] 
'''''
Created on 2012-7-5
 
@author: Administrator
''' 
import wx 
import wx 
class Example(wx.Frame): 
    def __init__(self,parent,title): 
        super(Example,self).__init__(parent,title=title,size=(500,300)) 
        self.InitUI() 
        self.Centre() 
        self.Show() 
    def InitUI(self): 
        wx.StaticText(self,label='x:',pos=(10,10)) 
        wx.StaticText(self,label='y:',pos=(10,30)) 
         
        self.st1 = wx.StaticText(self,label='',pos=(30,10)) 
        self.st2 = wx.StaticText(self,label='',pos=(30,30)) 
         
        self.Bind(wx.EVT_MOVE, self.OnMove) 
         
        self.SetSize((250, 180)) 
        self.SetTitle('Move event') 
        self.Centre() 
        self.Show(True)   
    def OnMove(self,e): 
        x,y = e.GetPosition() 
 
        self.st1.SetLabel(str(x)) 
        self.st2.SetLabel(str(y)) 
         
if __name__ == '__main__': 
    app = wx.App() 
    Example(None,title="gotoclass") 
    app.MainLoop() 


这个例子显示了当前位置的窗口,拖动窗口移动试试。
[python]
self.Bind(wx.EVT_MOVE, self.OnMove) 

这里我们将wx.EVT_MOVE事件绑定到OnMove方法上。
[python]
def OnMove(self, e): 
     
    x, y = e.GetPosition() 
    self.st1.SetLabel(str(x)) 
    self.st2.SetLabel(str(y)) 

在OnMove()方法的事件参数是一个对象,具体到一个特定的事件类型。在我们的例子,它是一个wx.MoveEvent类的实例。这个对象包含有关事件的信息。例如事件对象或窗口的位置。在我们的例子中,事件对象是wx.Frame的部件。我们用GetPosition()方法调用当前的位置。


事件绑定
在wxPython中,绑定是件很容易的事情,分三个步骤:
1.定义绑定的名字:wx.EVT_SIZE, wx.EVT_CLOSE等等。
2.创建事件处理,也就是方法。
3.绑定事件与方法。
[python] 
Bind(event, handler, source=None, id=wx.ID_ANY, id2=wx.ID_ANY) 

1.event就是一种EVT_ *对象
2.handler就是方法。
3.source是我们要从不同的小部件中区分相同的事件类型。
4.当我们有多个按钮、菜单项等id用于区分它们。

否决事件
有时我们需要停止处理一个事件。要做到这一点,我们调用这个方法Veto()。
[python]
import wx 
class Example(wx.Frame): 
    def __init__(self,parent,title): 
        super(Example,self).__init__(parent,title=title,size=(400,300)) 
        self.InitUI() 
        self.Centre() 
        self.Show() 
    def InitUI(self): 
        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) 
         
    def OnCloseWindow(self,e): 
        dial = wx.MessageDialog(None,"Are you Sure to Quit?","Question", 
                                wx.YES_NO|wx.NO_DEFAULT|wx.ICON_QUESTION) 
        ret = dial.ShowModal() 
         
        if ret == wx.ID_YES: 
            self.Destroy() 
        else: 
            e.Veto() 
         
if __name__ == '__main__': 
    app = wx.App() 
    Example(None,title="VetoMethod") 
    app.MainLoop() 

当我们处理关闭窗口时,需要给用户一个提示,是否真的退出程序。Veto()方法可以返回正在处理的事件。

事件传播
有两种类型的事件:基本事件和命令事件。他们有着不同的传播方法。基本事件不传播。命令事件可能传播。例如wx.CloseEvent是一个基本的事件。它并不适合这个事件传播到父窗口小部件。
默认情况下,事件,是在一个事件处理程序可以停止传播。如果要继续传播,我们必须调用Skip()方法。
[python]
import wx 
class MyPanel(wx.Panel): 
    def __init__(self,*args,**kw): 
        super(MyPanel,self).__init__(*args,**kw) 
        self.Bind(wx.EVT_BUTTON, self.OnButtonClicked) 
    def OnButtonClicked(self,e): 
        print "event reached panel class" 
        e.Skip() 
 
class MyButton(wx.Button): 
    def __init__(self,*args,**kw): 
        super(MyButton,self).__init__(*args,**kw) 
        self.Bind(wx.EVT_BUTTON, self.OnButtonClicked) 
    def OnButtonClicked(self,e): 
        print "event reached button class" 
        e.Skip() 
 
class Example(wx.Frame): 
    def __init__(self,*args,**kw): 
        super(Example,self).__init__(*args,**kw) 
        self.InitUI() 
    def InitUI(self): 
        mpnl = MyPanel(self) 
        MyButton(mpnl,label='Ok',pos=(15,15)) 
        self.Bind(wx.EVT_BUTTON, self.OnButtonClicked) 
         
        self.SetTitle("Propagation") 
        self.Centre() 
        self.Show() 
    def OnButtonClicked(self,e): 
        print "event reached frame class" 
        e.Skip() 
 
def main(): 
    ex = wx.App() 
    Example(None) 
    ex.MainLoop() 
if __name__ == '__main__': 
    main() 

这个例子中,frame里装着一个panel,一个button,当点button时它会把事件传播给panel,再传播给frame.
[python] view plaincopy
event reached button class 
event reached panel class 
event reached frame class 

如果你有兴趣,尝试省略一些Skip()方法,看看会发生什么。

组件的ID
识符是整数,惟一确定组件身份的事件系统。有三种方法可以创建的窗口id。
1.让系统自动创建。
2.使用标准ID
3.自己创建
[python] 
wx.Button(parent, -1) 
wx.Button(parent, wx.ID_ANY) 

上面两个-1与wx.ID_ANY都是让系统自动创建ID。但我们推荐使用标准ID或者自己创建ID。
[python]
import wx 
class Example(wx.Frame): 
    def __init__(self,*args,**kw): 
        super(Example,self).__init__(*args,**kw) 
        self.InitUI() 
    def InitUI(self): 
        panel = wx.Panel(self) 
        grid = wx.GridSizer(3,2) 
         
        grid.AddMany([(wx.Button(panel,wx.ID_CANCEL),0,wx.TOP|wx.LEFT,9), 
                      (wx.Button(panel, wx.ID_DELETE), 0, wx.TOP, 9), 
                      (wx.Button(panel, wx.ID_SAVE), 0, wx.LEFT, 9), 
                      (wx.Button(panel, wx.ID_EXIT)), 
                      (wx.Button(panel, wx.ID_STOP), 0, wx.LEFT, 9), 
                      (wx.Button(panel, wx.ID_NEW))]) 
         
        self.Bind(wx.EVT_BUTTON, self.OnQuitApp,id=wx.ID_EXIT) 
        panel.SetSizer(grid) 
         
        self.SetSize((220,180)) 
        self.SetTitle("window ID") 
        self.Centre() 
        self.Show() 
    def OnQuitApp(self, event): 
         
        self.Close() 
 
def main(): 
    ex = wx.App() 
    Example(None) 
    ex.MainLoop() 
if __name__ == '__main__': 
    main() 

这里我们使用的都是标准ID,如果在Liux,这些按钮都带图标。
[python] view plaincopy
self.Bind(wx.EVT_BUTTON, self.OnQuitApp, id=wx.ID_EXIT) 
指定ID后,像这个id=wx.ID_EXIT。就可以处理它的事件了。


创建自己的ID
让我们来看看自己如何创建ID:
[python] 
'''''
Created on 2012-7-5
 
@author: Administrator
''' 
import wx 
 
ID_MENU_NEW = wx.NewId() 
ID_MENU_OPEN = wx.NewId() 
ID_MENU_SAVE = wx.NewId() 
 
class Example(wx.Frame): 
    def __init__(self,*args,**kw): 
        super(Example,self).__init__(*args,**kw) 
        self.InitUI() 
    def InitUI(self): 
        self.CreateStatusBar() 
        self.CreateMenuBar() 
         
        self.SetSize((250, 180)) 
        self.SetTitle('My Own ID') 
        self.Centre() 
        self.Show(True)   
    def CreateMenuBar(self): 
        mb = wx.MenuBar() 
        fMenu = wx.Menu() 
        fMenu.Append(ID_MENU_NEW,'New') 
        fMenu.Append(ID_MENU_OPEN, 'Open') 
        fMenu.Append(ID_MENU_SAVE, 'Save') 
         
        mb.Append(fMenu,'&File') 
        self.SetMenuBar(mb) 
         
        self.Bind(wx.EVT_MENU, self.DisplayMessage,id=ID_MENU_NEW) 
        self.Bind(wx.EVT_MENU, self.DisplayMessage,id=ID_MENU_OPEN) 
        self.Bind(wx.EVT_MENU, self.DisplayMessage,id=ID_MENU_SAVE) 
    def DisplayMessage(self,e): 
        sb = self.GetStatusBar() 
        eid = e.GetId() 
         
        if eid == ID_MENU_NEW: 
            msg = 'New Menu item selected' 
        elif eid==ID_MENU_OPEN: 
            msg = 'Open menu item selected' 
        elif eid == ID_MENU_SAVE: 
            msg = 'Save menu item selected' 
         
        sb.SetStatusText(msg) 
         
def main(): 
     
    ex = wx.App() 
    Example(None) 
    ex.MainLoop()     
 
 
if __name__ == '__main__': 
    main()   

[python] view plaincopy
ID_MENU_NEW = wx.NewId() 
ID_MENU_OPEN = wx.NewId() 
ID_MENU_SAVE = wx.NewId() 

wx.NewId()方法可以帮你创建一个唯一的id号供你使用。

 作者:youyigong

相关内容

    暂无相关文章

评论关闭