Search code examples
windowswxpythonkeyeventkeycodepythoncard

PythonCard not getting 'enter' KeyEvent in Windows


I'm sorry if this is a newbie question, but I am writing a PythonCard program and I want it to do something when I press the enter key from inside a TextBox. My code is below:

def on_SampleTextField_keyDown(self, event):
    if event.keyCode == wx.WXK_RETURN:
        doSomething()
    else:
        event.Skip()

This works fine on Linux, but when I run it on Windows it just acts as the Tab key would. After searching the web I believe Windows is treating the enter key as a navigational key, and if I were using just wxPython I would need to set the window style to wx.WANTS_CHARS . I think this should be possible in PythonCard since it just sits on top of wxPython, but I'm not sure. And if it is I wouldn't know how to do it! So if anyone has any ideas, please let me know!


Solution

  • In wxPython I was able to use the return key when adding wx.TE_PROCESS_ENTER to the style of the TextCtrl and binding the wx.EVT_TEXT_ENTER event as described here.
    PythonCard neither defines this event nor can you manually alter the style of the TextField since this property is set in __init__(). Another option that worked for me in wxPython was binding to the wx.EVT_CHAR_HOOK event which does not require a certain style attribute to be set during initialisation. That's why I used this approach to come up with a somewhat hacky solution to the problem.

    PythonCard defines its events in class structures like this:

    class KeyPressEvent(KeyEvent):    
        name = 'keyPress'
        binding = wx.EVT_CHAR
        id = wx.wxEVT_CHAR
    

    I used this structure as a template for a new custom event so my code now looks something like this:

    from PythonCard import model
    from PythonCard.event import KeyEvent
    import PythonCard.components.textfield
    
    import wx
    
    class KeyPressHookEvent(KeyEvent):    
        name = 'keyPressHook'
        binding = wx.EVT_CHAR_HOOK
        id = wx.wxEVT_CHAR_HOOK
    
    # TextFieldEvents is a tuple so type juggling is needed to modify it
    PythonCard.components.textfield.TextFieldEvents = tuple(
            list(PythonCard.components.textfield.TextFieldEvents) + 
            [KeyPressHookEvent])
    

    Then I create my application as usual and define the handler:

    def on_keyPressHook(self, event):
        if event.keyCode == wx.WXK_RETURN:
            self.handle_return()
        else:
            event.Skip()
    

    That way I can handle the press of the return key in handle_return(). This works on Windows, but not in Cygwin and so maybe not on linux. At least in Cygwin the application still receives the press of the return key in on_keyDown() so all you have to do is to copy the content of on_keyPressHook() to that function.