thelost
thelost

Reputation: 705

Check if key is held down, wxpython?

Hello i am wondering if there is a way to check if a certain key is being held down.

Here is an example of the situation

self.button2.Bind(wx.EVT_LEFT_DOWN, self.clickedbutton)
def clickedbutton(self, e):
    if (Control is held down while the button has been clicked):
        print "it works"

Thanks

Upvotes: 4

Views: 3483

Answers (3)

James C. Ahlstrom
James C. Ahlstrom

Reputation: 1

WxPython has a function wx.GetKeyState(key) that returns True if the key is currently down. It succeeds for all keys on Windows. But the documentation states that "In wxGTK, this function can be only used with modifier keys ( WXK_ALT , WXK_CONTROL and WXK_SHIFT ) when not using X11 backend currently".

Here is a portable alternative. It uses a filter function as part of the App to filter all events. It captures the key up and key down events. It can be extended to other events.

class App(wx.App):
    def __init__(self):
        self.keys_down = []
    def FilterEvent(self, event):
        typ = event.GetEventType()
        if typ == wx.EVT_KEY_DOWN.typeId:
            key = event.GetKeyCode()  # This is always upper case
            if key not in self.keys_down:
                self.keys_down.append(key)
                print (self.keys_down)
        elif typ == wx.EVT_KEY_UP.typeId:
            key = event.GetKeyCode()
            self.keys_down.remove(key)
            print (self.keys_down)
        return -1
    def QuiskGetKeyState(self, key): # Replacement for wx.GetKeyState()
        if 97 <= key <= 122:    # convert to upper case
            key -= 32
        return key in self.keys_down

Upvotes: 0

GP89
GP89

Reputation: 6730

self.button2.Bind(wx.EVT_LEFT_DOWN, self.clickedbutton)
def clickedbutton(self, e):
    if wx.GetKeyState(wx.WXK_CONTROL):
        print "it works"

Upvotes: 9

Toni Ruža
Toni Ruža

Reputation: 7512

The problem with using only wx for this is that you need a KeyEvent to access the actual state of the control key. Since you need this information outside of such an event you need to keep track of it manually, and the problem with that is that it is easy to miss a KeyEvent since only focused controls get them and you can't count on them propagating.

The foolproof way would be to utilize some platform specific way of querying this information, if you are on windows look in to pyHook or win32api for this.

In some cases though the wx only approach can work and here is how you do it:

import wx


class Example(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None)

        btn = wx.Button(self, label="press me")
        self.Sizer = wx.BoxSizer()
        self.Sizer.Add(btn)

        self.ctrl_down = False

        self.Bind(wx.EVT_KEY_UP, self.OnUpdateCtrlState)
        self.Bind(wx.EVT_KEY_DOWN, self.OnUpdateCtrlState)
        btn.Bind(wx.EVT_KEY_UP, self.OnUpdateCtrlState)
        btn.Bind(wx.EVT_KEY_DOWN, self.OnUpdateCtrlState)
        btn.Bind(wx.EVT_BUTTON, self.OnButton)

    def OnUpdateCtrlState(self, event):
        self.ctrl_down = event.ControlDown()
        print self.ctrl_down
        event.Skip()

    def OnButton(self, event):
        if self.ctrl_down:
            wx.MessageBox("control down")


app = wx.App(False)
app.TopWindow = f = Example()
f.Show()
app.MainLoop()

Upvotes: 4

Related Questions