wxpython事件

2024-04-18 05:38
文章标签 事件 wxpython

本文主要是介绍wxpython事件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

事件是每一个GUI应用程序的组成部分。所有的GUI应用程序是事件驱动的。应用程序反应,以产生不同的事件,在其生命周期类型。事件的产生主要是由应用程序的用户。但它们可以产生,以及通过其他手段。例如互联网连接,窗口管理器,定时器。所以,当我们调用mainloop()方法,等待我们的应用程序产生事件。 mainloop()方法结束时退出应用程序。

定义

事件是一个从底层框架,通常的GUI工具包的应用程序级信息的一块。事件循环是一种编程构造和调度事件或程序中的消息等待。事件循环反复查找进程的事件。调度程序是一个过程,映射事件到事件处理程序。事件处理程序,对事件作出反应的方法。

事件对象是与事件相关联的对象。它通常是一个窗口。事件类型是一个已产生的独特的事件。事件绑定是一个对象,结合事件处理程序的事件类型。

一个简单的例子

这个例子里面讨论move事件。类型是wx.Movie的事件。此事件绑定是wx.EVT_MOTION。

'''
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()


这个例子显示了当前位置的窗口,拖动窗口移动试试。

self.Bind(wx.EVT_MOVE, self.OnMove)

这里我们将wx.EVT_MOVE事件绑定到OnMove方法上。

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.绑定事件与方法。

Bind(event, handler, source=None, id=wx.ID_ANY, id2=wx.ID_ANY)

1.event就是一种EVT_ *对象

2.handler就是方法。

3.source是我们要从不同的小部件中区分相同的事件类型。

4.当我们有多个按钮、菜单项等id用于区分它们。


否决事件
有时我们需要停止处理一个事件。要做到这一点,我们调用这个方法Veto()。

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()方法。

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.

event reached button class
event reached panel class
event reached frame class

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


组件的ID

识符是整数,惟一确定组件身份的事件系统。有三种方法可以创建的窗口id。

1.让系统自动创建。

2.使用标准ID

3.自己创建

wx.Button(parent, -1)
wx.Button(parent, wx.ID_ANY)

上面两个-1与wx.ID_ANY都是让系统自动创建ID。但我们推荐使用标准ID或者自己创建ID。

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,这些按钮都带图标。

self.Bind(wx.EVT_BUTTON, self.OnQuitApp, id=wx.ID_EXIT)
指定ID后,像这个id=wx.ID_EXIT。就可以处理它的事件了。



创建自己的ID

让我们来看看自己如何创建ID:

'''
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()  

ID_MENU_NEW = wx.NewId()
ID_MENU_OPEN = wx.NewId()
ID_MENU_SAVE = wx.NewId()

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


重绘事件

我们窗口变大变小时或当我们最大化时,就会产生一个重绘事件。

import wx
class Example(wx.Frame):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw) 
self.InitUI()
def InitUI(self):
self.count = 0
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.SetSize((250, 180))
self.Centre()
self.Show(True)  
def OnPaint(self,e):
self.count += 1
self.SetTitle(str(self.count))
def main():
ex = wx.App()
Example(None)
ex.MainLoop()    
if __name__ == '__main__':
main()  

焦点事件:

'''
Created on 2012-7-5
@author: Administrator
'''
import wx
class MyWindow(wx.Panel):
def __init__(self,parent):
super(MyWindow,self).__init__(parent)
self.color = '#b3b3b3'
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
def OnPaint(self,e):
dc = wx.PaintDC(self)
dc.SetPen(wx.Pen(self.color))
x,y = self.GetSize()
dc.DrawRectangle(0,0,x,y)
def OnSize(self,e):
self.Refresh()
def OnSetFocus(self,e):
self.color = '#0099f7'
self.Refresh()
def OnKillFocus(self,e):
self.color = '#b3b3b3'
self.Refresh()
class Example(wx.Frame):
def __init__(self,*args,**kw):
super(Example,self).__init__(*args,**kw)
self.InitUI()
def InitUI(self):
grid = wx.GridSizer(2,2,10,10)
grid.AddMany([(MyWindow(self),0,wx.EXPAND|wx.TOP|wx.LEFT,9),
(MyWindow(self), 0, wx.EXPAND|wx.TOP|wx.RIGHT, 9), 
(MyWindow(self), 0, wx.EXPAND|wx.BOTTOM|wx.LEFT, 9), 
(MyWindow(self), 0, wx.EXPAND|wx.BOTTOM|wx.RIGHT, 9)])
self.SetSizer(grid)
self.SetSize((350, 250))
self.SetTitle('Focus event')
self.Centre()
self.Show(True)  
def main():
ex = wx.App()
Example(None)
ex.MainLoop()    
if __name__ == '__main__':
main()  
上面例子中,四个panel,最亮的那个panel就是焦点。


键盘事件

当你敲击键盘时,键盘事件就产生了。它针对的就是当前获得焦点的控件。有三种不同的处理方法:

wx.EVT_KEY_DOWN
wx.EVT_KEY_UP
wx.EVT_CHAR

我们来看一下这个例子,当你按下Esc键时,来关闭程序。

import wx
class Example(wx.Frame):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw) 
self.InitUI()
def InitUI(self):
pnl = wx.Panel(self)
pnl.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
pnl.SetFocus()
self.SetSize((250, 180))
self.SetTitle('Key event')
self.Centre()
self.Show(True)  
def OnKeyDown(self,e):
key = e.GetKeyCode()
if key == wx.WXK_ESCAPE:
ret = wx.MessageBox("Are you sure to quit?","Question",
wx.YES_NO|wx.NO_DEFAULT,self)
if ret == wx.YES:
self.Close()
def main():
ex = wx.App()
Example(None)
ex.MainLoop()    



这篇关于wxpython事件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/913902

相关文章

Python中的异步:async 和 await以及操作中的事件循环、回调和异常

《Python中的异步:async和await以及操作中的事件循环、回调和异常》在现代编程中,异步操作在处理I/O密集型任务时,可以显著提高程序的性能和响应速度,Python提供了asyn... 目录引言什么是异步操作?python 中的异步编程基础async 和 await 关键字asyncio 模块理论

禁止平板,iPad长按弹出默认菜单事件

通过监控按下抬起时间差来禁止弹出事件,把以下代码写在要禁止的页面的页面加载事件里面即可     var date;document.addEventListener('touchstart', event => {date = new Date().getTime();});document.addEventListener('touchend', event => {if (new

FreeRTOS内部机制学习03(事件组内部机制)

文章目录 事件组使用的场景事件组的核心以及Set事件API做的事情事件组的特殊之处事件组为什么不关闭中断xEventGroupSetBitsFromISR内部是怎么做的? 事件组使用的场景 学校组织秋游,组长在等待: 张三:我到了 李四:我到了 王五:我到了 组长说:好,大家都到齐了,出发! 秋游回来第二天就要提交一篇心得报告,组长在焦急等待:张三、李四、王五谁先写好就交谁的

【经验交流】修复系统事件查看器启动不能时出现的4201错误

方法1,取得『%SystemRoot%\LogFiles』文件夹和『%SystemRoot%\System32\wbem』文件夹的权限(包括这两个文件夹的所有子文件夹的权限),简单点说,就是使你当前的帐户拥有这两个文件夹以及它们的子文件夹的绝对控制权限。这是最简单的方法,不少老外说,这样一弄,倒是解决了问题。不过对我的系统,没用; 方法2,以不带网络的安全模式启动,运行命令行,输入“ne

BT天堂网站挂马事件后续:“大灰狼”远控木马分析及幕后真凶调查

9月初安全团队披露bt天堂网站挂马事件,该网站被利用IE神洞CVE-2014-6332挂马,如果用户没有打补丁或开启安全软件防护,电脑会自动下载执行大灰狼远控木马程序。 鉴于bt天堂电影下载网站访问量巨大,此次挂马事件受害者甚众,安全团队专门针对该木马进行严密监控,并对其幕后真凶进行了深入调查。 一、“大灰狼”的伪装 以下是10月30日一天内大灰狼远控的木马样本截图,可以看到该木马变种数量不

react笔记 8-19 事件对象、获取dom元素、双向绑定

1、事件对象event 通过事件的event对象获取它的dom元素 run=(event)=>{event.target.style="background:yellowgreen" //event的父级为他本身event.target.getAttribute("aid") //这样便获取到了它的自定义属性aid}render() {return (<div><h2>{

react笔记 8-18 事件 方法 定义方法 获取/改变数据 传值

1、定义方法并绑定 class News extends React.Component {constructor(props) {super(props)this.state = {msg:'home组件'}}run(){alert("我是一个run") //方法写在类中}render() {return (<div><h2>{this.state.msg}</h2><button onCli

【Qt】定时器事件

定时器事件 在之前学习QTimer中实现了定时器的功能,而在QTimer背后是QTimerEvent定时器事件进行支撑的。在QObject中提供了一个timeEvent这个函数。 startTimer启动定时器killTimer关闭定时器 Qt 中在进⾏窗⼝程序的处理过程中,经常要周期性的执⾏某些操作,或者制作⼀些动画效果,使⽤定 时器就可以实现。所谓定时器就是在间隔⼀定时间后,去执⾏某⼀

Imageview在百度地图中实现点击事件

1.首先第一步,需要声明的全局有关类的引用 private BMapManager mBMapMan; private MapView mMapView; private MapController mMapController; private RadioGroup radiogroup; private RadioButton normalview; private RadioBu

Winform中在窗体中的Paint事件中重绘会导致递归问题?

在 WinForms 应用程序中,如果在窗体的 Paint 事件处理程序中不断调用 Invalidate 方法,确实可能会导致递归调用的问题。这是因为每次调用 Invalidate 方法时,都会向消息队列添加一个绘制消息,当消息队列中的绘制消息被处理时,会触发 Paint 事件。如果 Paint 事件处理程序中又调用了 Invalidate,就会形成一个循环,导致递归调用 Paint 事件,这