这个问题解决了使用wxPython发布事件所需的EvtHandler
非常具体的问题。
我正在使用Python 2.7。 在下面的示例中,我有两种事件:
StartMeausuringEvent
在wx.Panel
派生对象(DisplayPanel
)内触发,因此我使用self.GetEventHandler()
,即使绑定位于父对象中,也可以使用NewResultEvent
。 / LI>
threading.Thread
是从MeasurementThread
派生对象(wx.Frame
)触发的,它没有事件处理程序,因此我被迫发送一个事件处理程序,我选择了MeasurementFrame
派生对象(import wx
import time
import threading
import numpy as np
import wx.lib.newevent
# Create two new event types
StartMeasuringEvent, EVT_START_MEASURING = wx.lib.newevent.NewCommandEvent()
NewResultEvent, EVT_NEW_RESULT = wx.lib.newevent.NewEvent()
class MeasurementFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, title="Lets measure!", size=(300, 300))
# Layout
self.view = DisplayPanel(self)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(self.view, 1, wx.ALIGN_CENTER)
self.SetSizer(sizer)
self.SetMinSize((300, 300))
self.CreateStatusBar()
# Create a new measuring device object to embody a physical measuring device
self.device = MeasuringDevice(self.GetEventHandler(), amplification=10)
# Bind events to the proper handlers
self.Bind(EVT_START_MEASURING, self.OnStartMeasurement)
self.Bind(EVT_NEW_RESULT, self.OnNewResult)
def OnStartMeasurement(self, evt):
self.view.SetStatus("Measuring")
self.device.start_measurement()
def OnNewResult(self, evt):
self.view.SetStatus("New Result!")
print evt.result_data
class DisplayPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
# Attributes
self._result_display = wx.StaticText(self, label="0")
self._result_display.SetFont(wx.Font(16, wx.MODERN, wx.NORMAL, wx.NORMAL))
self._status_display = wx.StaticText(self, label="Ready!")
self._status_display.SetFont(wx.Font(8, wx.MODERN, wx.NORMAL, wx.NORMAL))
# Layout
sizer = wx.BoxSizer(wx.VERTICAL)
button1 = wx.Button(self, wx.NewId(), "Increment Counter")
# button2 = wx.Button(self, wx.NewId(), "Decrease Counter")
sizer.AddMany([(button1, 0, wx.ALIGN_CENTER),
# (button2, 0, wx.ALIGN_CENTER),
((15, 15), 0),
(self._result_display, 0, wx.ALIGN_CENTER),
(self._status_display, 0, wx.ALIGN_LEFT)])
self.SetSizer(sizer)
# Event Handlers
button1.Bind(wx.EVT_BUTTON, self.OnButton)
def OnButton(self, evt):
""" Send an event ... but to where? """
wx.PostEvent(self.GetEventHandler(), StartMeasuringEvent(self.GetId()))
def SetStatus(self, status=""):
""" Set status text in the window"""
self._status_display.SetLabel(status)
class MeasuringDevice:
def __init__(self, event_handler, amplification=10):
self.amplification = amplification
self.event_handler = event_handler # The object to which all event are sent
def start_measurement(self, repetitions=1):
""" Start a thread that takes care of obtaining a measurement """
for n in range(repetitions):
worker = MeasurementThread(self.event_handler, self.amplification)
worker.start()
class MeasurementThread(threading.Thread):
def __init__(self, event_handler, amplification):
threading.Thread.__init__(self)
self.event_handler = event_handler
self.amplification = amplification
def run(self):
print("Beginning simulated measurement")
time.sleep(1) # My simulated calculation time
result = np.random.randn()*self.amplification
evt = NewResultEvent(result_data=result)
wx.PostEvent(self.event_handler, evt)
print("Simulated Measurement done!")
if __name__ == '__main__':
my_app = wx.App(False)
my_frame = MeasurementFrame(None)
my_frame.Show()
my_app.MainLoop()
)的事件处理程序,因为这也是最终“碰撞”事件的对象。为什么第一个工作,因为对象?更一般地说,事件处理程序与“捕获”事件的对象之间的连接有多紧密?
/**
* Sends ArDrone the gaz value. Makes drone to move up or down
*
* @param value - value between -1 and 1.
*/
public void setGaz(final float value) {
droneProxy.setControlValue(CONTROL_SET_GAZ, value);
}
/**
* Sends ArDrone the Roll value. Makes drone to move left or right
*
* @param value - value between -1 and 1.
*/
public void setRoll(final float value) {
droneProxy.setControlValue(CONTROL_SET_ROLL, value);
}
/**
* Sends ArDrone the Pitch value. Makes drone to move forward or backward
*
* @param value - value between -1 and 1.
*/
public void setPitch(final float value) {
droneProxy.setControlValue(CONTROL_SET_PITCH, value);
}
/**
* Sends ArDrone the gaz value. Makes drone to turn left or right
*
* @param value - value between -1 and 1.
*/
public void setYaw(final float value) {
droneProxy.setControlValue(CONTROL_SET_YAW, value);
}
答案 0 :(得分:1)
第一个可行,因为命令事件自动向上传播包含层次结构(a.k.a窗口父/子连接),直到找到匹配的绑定或直到它到达顶级父窗口(如框架或对话框)。有关更多说明,请参阅幻灯片53中的http://wiki.wxpython.org/self.Bind%20vs.%20self.button.Bind和http://wxpython.org/OSCON2006/wxPython-intro-OSCON2006.pdf。
在查找匹配的事件绑定时,事件处理器将搜索特定路径。简而言之:如上所述,直接或间接从wx.CommandEvent
派生的事件类型将继续搜索父项,直到找到匹配项,而对于其他类型的事件,它只会在窗口中查找绑定事件已发送到并且不会传播到父窗口。如果处理程序调用{{1}},那么当处理程序返回事件时,处理器将继续寻找另一个匹配处理程序(仍然限于非命令事件的同一窗口。)很多更多除此之外,(参见上面链接的PDF中的幻灯片52)但是如果你理解了这一点,那么对于你可能遇到的几乎所有事件绑定/处理情况就足够了。
顺便说一句,event.Skip()
类派生自wx.Window
,所以除非你做过像wx.EvtHandler
这样的事情,否则PushEventHandler
会返回窗口本身。因此,除非你需要推送新的事件处理程序实例(大多数Python程序没有,它在C ++中更常用),然后你可以通过使用window.GetEventHandler()
代替window
来保存一些输入。