1

Well I have come up with some code to check what key is pressed, its pretty basic right now, but as I progress I will update here, the point is to get a key pressed whenever the key event takes place

import wx

class Example(wx.Frame):
    def __init__(self, *args,**kw):
        super(Example, self).__init__(*args,**kw)
        self.InitUI()
    def InitUI(self):
        #frame = wx.Frame(self, style=wx.FRAME_DRAWER | wx.STAY_ON_TOP, size = (100, 100))
        #pnl= wx.Panel(frame)
        pnl= wx.Panel(self)    
        pnl.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
        self.st1 = wx.StaticText(self, label='', pos=(30, 10))
        pnl.SetFocus()
        self.SetSize((250,180))
        self.SetTitle('Key Press Event')
        self.Centre()
        self.Show(True)

    def OnKeyDown(self, e):
        key = e.GetKeyCode()
        if  key==wx.WXK_ESCAPE:
            self.st1.SetLabel("ESCAPE")
        elif key ==wx.WXK_CONTROL:
            self.st1.SetLabel("CTRL")
        elif key==wx.WXK_ALT:
            self.st1.SetLabel("ALT")
        elif key==wx.WXK_BACK:
            self.st1.SetLabel("BACKSPACE")
        elif key== wx.WXK_EXECUTE:
            self.st1.SetLabel("ENTER KEY")
def main():
    ex = wx.App()
    Example(None)
    ex.MainLoop()

if __name__=='__main__':
    main()

I am trying to to a borderless window for this but even if I put the panel in a frame with style= FRAME_DRAWER it doesnt work, neither does the STAY_ON_TOP so those two lines are commented please see if u can make it work..

1 Answer 1

2

Panels tend to eat key events or pass them on to other widgets. See

http://wxpython-users.1045709.n5.nabble.com/Catching-key-events-from-a-panel-and-follow-up-to-stacked-panels-td2360109.html

Which links to an old thread: http://article.gmane.org/gmane.comp.python.wxpython/50485

Quoting Robin Dunn, creator of wxPython:

  • Bind a key event handler to all the widgets

  • *Catch the EVT_CHILD_FOCUS event and reset the focus back to where you want it to be whenever the focus changes to a child.*

  • Use a wx.AcceleratorTable instead of key events, so the keystrokes will be turned into menu events no matter which widget in the app has the focus.

  • Bind your key handler to the app instead of to the frame. All unhandled events are sent to the app object before they are abandoned, so whichever widget has the focus, if it doesn't handle the key event itself then the app will get a chance at it.

You might also find my old tutorial on key events enlightening as well.

Sign up to request clarification or add additional context in comments.

4 Comments

how to bind your key handler to the app instead ... ? Can you provide a small example @MikeDriscoll?
Are you referring to an AcceleratorTable? That is probably the easiest way to go to catch certain keys. Otherwise you'll have to hook into something like the OS-level side of things.
Can we catch CTRL + S with AcceleratorTable no matter which widget has the focus? Would you have a minimal example?
I believe it will work in most cases as long as your application has the focus. There may be some edge cases I'm not thinking of right now as I don't use wxPython at my current job except for fun. Here's an article on the topic that I wrote: blog.pythonlibrary.org/2010/12/02/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.