Question

I want my wxPython application to trigger an event when a text entry widget loses focus. I've followed the tutorial here, which describes using wx.EVT_KILL_FOCUS. However, I'm getting unexpected behavior.

The following code works fine:

import wx

class MyForm(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "Focus Tutorial 1a")
        panel = wx.Panel(self, wx.ID_ANY)
        txt = wx.TextCtrl(panel, wx.ID_ANY, "")

        txt.Bind(wx.EVT_KILL_FOCUS, self.onTextKillFocus)
        """
        This next line seems to be important for working correctly,
        but I don't understand why:
        """
        txt.Bind(wx.EVT_SET_FOCUS, self.onTextFocus)

        btn = wx.Button(panel, wx.ID_ANY, "Test")

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(txt, 0, wx.ALL, 5)
        sizer.Add(btn, 0, wx.ALL, 5)
        panel.SetSizer(sizer)

    def onTextFocus(self, event):
        print "text received focus!"

    def onTextKillFocus(self, event):
        print "text lost focus!"

if __name__ == '__main__':
    app = wx.App()
    frame = MyForm().Show()
    app.MainLoop()

When I tab back and forth from the text control to the button, or click in or out of the text control, I get the focus messages I expect.

However, when I make the following (reasonable?) edit, things go south:

import wx

class MyForm(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "Focus Tutorial 1a")
        panel = wx.Panel(self, wx.ID_ANY)
        txt = wx.TextCtrl(panel, wx.ID_ANY, "")

        txt.Bind(wx.EVT_KILL_FOCUS, self.onTextKillFocus)
        """
        This next line seems to be important for working correctly,
        but I don't understand why:
        """
##        txt.Bind(wx.EVT_SET_FOCUS, self.onTextFocus)

        btn = wx.Button(panel, wx.ID_ANY, "Test")

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(txt, 0, wx.ALL, 5)
        sizer.Add(btn, 0, wx.ALL, 5)
        panel.SetSizer(sizer)

    def onTextFocus(self, event):
        print "text received focus!"

    def onTextKillFocus(self, event):
        print "text lost focus!"

if __name__ == '__main__':
    app = wx.App()
    frame = MyForm().Show()
    app.MainLoop()

The unexpected behavior is that when I try to change focus from the text box to anything else (tabbing or mouse clicks), the 'text lost focus!' message prints once, and never again, and I can no longer edit the contents of the text control.

Is this expected behavior? If not, what am I doing wrong?

Python version 2.7, wxPython version 3.0.0.0, Windows 7 64-bit

Was it helpful?

Solution

As explained in wxEvent::Skip() documentation, you should almost invariably call it for non-command events as you don't want to prevent the default handling from taking place.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top