wxpython在wx.Frame中捕获键盘事件

7 投票
2 回答
8632 浏览
提问于 2025-04-17 09:25

我正在尝试捕捉在 wx.Frame 里面发生的键盘事件,我本以为下面的代码可以做到这一点。但是,当我运行代码时,处理函数 OnKeyDown 从来没有被调用:

import logging as log
import wx

class MainWindow(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(200,100))

        self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
        self.Bind(wx.EVT_KEY_UP, self.OnKeyDown)
        self.Bind(wx.EVT_CHAR, self.OnKeyDown)
        self.SetFocus()
        self.Show(True)

    def OnKeyDown(self, event=None):
        log.debug("OnKeyDown event %s" % (event))

if __name__ == "__main__":
    app = wx.App(False)
    gui = MainWindow(None, "test")
    app.MainLoop()

如果有人知道该怎么做,我会非常感激你的帮助。

2 个回答

10

我发现我可以在框架中添加一个面板,而面板对键盘事件的响应要好得多。

import wx

class MainWindow(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(200,100))

        self.panel = wx.Panel(self, wx.ID_ANY)
        self.panel.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
        self.panel.Bind(wx.EVT_KEY_UP, self.OnKeyDown)
        self.panel.Bind(wx.EVT_CHAR, self.OnKeyDown)
        self.panel.SetFocus()
        self.Show(True)

    def OnKeyDown(self, event=None):
        print "Event!"

if __name__ == "__main__":
    app = wx.App(False)
    gui = MainWindow(None, "test")
    app.MainLoop()
3

你的代码在使用 log.warning 的时候是可以正常工作的。

log.warning("OnKeyDown event %s" % (event))

日志的级别有:

Level    Value
CRITICAL  50
ERROR     40
WARNING   30
INFO      20
DEBUG     10
UNSET      0

默认的日志级别是 WARNING。只有高于这个默认级别的日志才会被记录。所以在默认级别(30)下,log.infolog.debug 都不会有任何输出。

根据提问者的评论进行编辑:设置正确的日志级别可以让你的代码在 winXP 32位和 win7 64位上,使用 python 2.6 和 wxpython 2.8.11 以及 2.8.12 时运行得很好。不过,这段代码在 ubuntu 上却不知为何无法运行。这种差异与 wxwidgets 在不同操作系统上的实现方式有关,而不是与日志记录有关。正如你已经发现的,要让它在 ubuntu 上正常工作,需要添加一个面板,并使用合适的日志级别。所以这样做是可以的:

class MainWindow(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(200,100))
        self.panel =  wx.Panel(self, wx.ID_ANY)
        self.Bind(wx.EVT_KEY_DOWN, self.KeyDown)
        self.Bind(wx.EVT_KEY_UP, self.KeyDown)
        self.Bind(wx.EVT_CHAR, self.KeyDown)
        self.panel.SetFocus()

    def KeyDown(self, event=None):
        logging.warning("OnKeyDown event %s" % (event))

if __name__ == "__main__":
    app = wx.App(False)
    gui = MainWindow(None, "test")
    gui.Show()
    app.MainLoop()

撰写回答