Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 793
Kevin Avatar asked Jan 03 '12 02:01

Kevin


2 Answers

I figured out that I can add a panel to the frame, and a panel is much more receptive of keyboard events.

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()
like image 154
Kevin Avatar answered Sep 30 '22 23:09

Kevin


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()
like image 40
joaquin Avatar answered Sep 30 '22 23:09

joaquin