views:

124

answers:

1

I'm having a bit of trouble with a panel that has two wxPython TextCtrls in it. I want either an EVT_CHAR or EVT_KEY_UP handler bound to both controls, and I want to be able to tell which TextCtrl generated the event. I would think that event.Id would tell me this, but in the following sample code it's always 0. Any thoughts? I've only tested this on OS X.

This code simply checks that both TextCtrls have some text in them before enabling the Done button

import wx

class MyFrame(wx.Frame):
    def __init__(self, parent, ID, title):
        wx.Frame.__init__(self, parent, ID, title,
                         wx.DefaultPosition, wx.Size(200, 150))
        self.panel = BaseNameEntryPanel(self)

class BaseNameEntryPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1)

        self.entry = wx.TextCtrl(self, wx.NewId())
        self.entry2 = wx.TextCtrl(self, wx.NewId())

        self.donebtn = wx.Button(self, wx.NewId(), "Done")
        self.donebtn.Disable()

        vsizer = wx.BoxSizer(wx.VERTICAL)

        vsizer.Add(self.entry, 1, wx.EXPAND|wx.GROW)
        vsizer.Add(self.entry2, 1, wx.EXPAND|wx.GROW)
        vsizer.Add(self.donebtn, 1, wx.EXPAND|wx.GROW)
        self.SetSizer(vsizer)
        self.Fit()
        self.entry.Bind(wx.EVT_KEY_UP, self.Handle)
        self.entry2.Bind(wx.EVT_KEY_UP, self.Handle)


    def Handle(self, event):
        keycode = event.GetKeyCode()
        print keycode, event.Id # <- event.Id is always 0!

        def checker(entry):
            return bool(entry.GetValue().strip())

        self.donebtn.Enable(checker(self.entry) and checker(self.entry2))



class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(None, -1, "Hello from wxPython")
        frame.Show(True)
        self.SetTopWindow(frame)
        return True

app = MyApp(0)
app.MainLoop()
+3  A: 

You could try event.GetId() or event.GetEventObject() and see if either of these work.

Another approach to this is to use lambda or functools.partial to effectively pass a parameter to the handler. So, for example, sub in the lines below into your program:

        self.entry.Bind(wx.EVT_KEY_UP, functools.partial(self.Handle, ob=self.entry))
        self.entry2.Bind(wx.EVT_KEY_UP, functools.partial(self.Handle, ob=self.entry2))

    def Handle(self, event, ob=None):
            print ob

And then ob will be either entry or entry2 depending on which panel is clicked. But, of course, this shouldn't be necessary, and GetId and GetEventObject() should both work -- though I don't (yet) have a Mac to try these on.

tom10
event.GetEventObject().GetId() worked great, thanks. Nice idea as well with functools.partial!
Jay P.