如何在wxPython模态配置对话框中捕获协程发送的EVT_FOOTSWITCH事件?
解决脚踏开关事件在模态对话框中的捕获问题
方案1:主窗口转发事件给ConfigDialog
这是最直接的修改方式,无需改动原有协程逻辑,仅在主窗口的事件处理函数中判断ConfigDialog是否处于显示状态,若满足条件则转发事件。
主窗口代码示例:
class FootswitchMonitor(wx.Frame): def __init__(self): super().__init__(None) self.config_dialog = None self.Bind(wx.EVT_FOOTSWITCH, self.on_footswitch_event) # 启动捕获脚踏开关的协程逻辑... def open_config_dialog(self): self.config_dialog = ConfigDialog(self) self.config_dialog.ShowModal() self.config_dialog = None def on_footswitch_event(self, event): # 若配置对话框已打开,转发事件 if self.config_dialog and self.config_dialog.IsShown(): wx.PostEvent(self.config_dialog, event) # 保留主窗口自身的事件处理(如果需要) event.Skip()
ConfigDialog代码示例:
class ConfigDialog(wx.Dialog): def __init__(self, parent): super().__init__(parent, style=wx.DEFAULT_DIALOG_STYLE) self.Bind(wx.EVT_FOOTSWITCH, self.on_footswitch_event) def on_footswitch_event(self, event): # 在这里处理脚踏开关事件 print("配置对话框收到脚踏开关事件") event.Skip()
方案2:动态切换协程的事件投递目标
修改协程的事件发送逻辑,让它不再固定投递到主窗口,而是投递到一个可动态修改的目标对象。当ConfigDialog打开时,将目标切换为对话框;关闭后切回主窗口。
主窗口代码示例:
class FootswitchMonitor(wx.Frame): def __init__(self): super().__init__(None) self.event_target = self # 初始事件目标为主窗口 self.Bind(wx.EVT_FOOTSWITCH, self.on_footswitch_event) # 启动捕获协程,协程中使用self.event_target作为投递目标 # async def capture_footswitch(): # while True: # # 捕获设备事件并构造EVT_FOOTSWITCH事件 # foot_event = FootswitchEvent(wx.EVT_FOOTSWITCH.typeId) # wx.PostEvent(self.event_target, foot_event) # await asyncio.sleep(0.01) def open_config_dialog(self): self.config_dialog = ConfigDialog(self) self.event_target = self.config_dialog # 切换目标到对话框 self.config_dialog.ShowModal() self.event_target = self # 恢复目标为主窗口 self.config_dialog = None
ConfigDialog的事件绑定逻辑同方案1,无需额外修改。
不推荐的方案:暂停主协程并启动新协程
不建议采用这种方式,原因如下:
- 设备已被主协程
grab,新协程无法再次获取设备控制权,强行尝试可能引发设备资源冲突或异常。 - 暂停主协程会导致事件捕获中断,恢复时容易出现设备状态不一致、事件丢失等问题,大幅增加代码复杂度和调试难度。
内容的提问来源于stack exchange,提问作者Emilio Conte
相关产品推荐
相关产品推荐

