Search code examples
pythonwxpythonwxwidgets

wxpython capture keyboard events in a wx.Frame


I'm trying to capture keyboard events that happen inside a wx.Frame, and I would expect the following code to capture those events. However, the handler OnKeyDown is never called when I run the code:

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

If anyone knows how to do this, I would appreciate some help.


Solution

  • Your code works if you use log.warning.

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

    Logging levels are:

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

    The default logging level is WARNING. Only logs with levels higher than the default are produced. So, at the default level (30), neither log.info nor log.debug produce any output.

    Edited after OP comments: Setting the correct level of logging make your code works perfect on winXP 32bit and win7 64bit with python 2.6 and wxpython 2.8.11 and 2.8.12. The code however doesn't work on ubuntu for some reason I don't know. This difference is related with how wxwidgets is implemented in different SO's but not with logging. As you already discovered, for it to work in ubuntu, it needs a panel to be added as well as the use of the adequate logging level. So this works:

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