Catching wx events

Chris Mellon arkanes at gmail.com
Thu Jan 18 10:14:56 EST 2007


On 18 Jan 2007 06:12:17 -0800, Cruelemort <ian.inglis at gmail.com> wrote:
> Hello all,
>
> I am new to this group (and new to Python) and was hoping someone would
> be able to help me with something, it is not so much a problem it is
> more of a general interest query about something i have a solution too
> but am not sure it is the correct one.
>
> I have a class that contains a string ID and a name, and a list
> containing a few objects of this type, i need to loop through this list
> and create a button for each object (with the name as the label) i have
> done this with the following code -
>
>                 for chan in self._channellist:
>                         channelbutton = wx.Button(self, id=-1,
> label=chan.getName())
>
> channelbutton.Bind(wx.EVT_BUTTON,self._channelChanged)
>
> My question is this - in the _channelChanged method, how do i know
> which button has been pressed when i enter the channel changed method,
> and so how do i retrieve the appropriate object depending on which
> button has been pressed?
>
> I have potentially solved this problem using the UserData property in a
> sizer, i have added all the buttons to a sizer for display purposes and
> so SizerItem objects have been created, i can then set the original
> object to the UserData object by putting the following line of code in
> the loop
>
>                         sizeritem =
> self.topsizer.Add(channelbutton,0,wx.ALIGN_RIGHT, userData=chan)
>
> This way i can retrieve the item in the _channelChanged method with the
> following -
>
>         def _channelChanged(self, event):
>                 eventobj = event.GetEventObject()
>                 chan = self.topsizer.GetItem(eventobj).GetUserData()
>
>
> This works fine but by looking at the API it would appear the UserData
> property is not really designed for this use ("userData - Allows an
> extra object to be attached to the sizer item, for use in derived
> classes when sizing information is more complex than the proportion and
> flag will allow for").
>
> Another option would be to derive my own Button class and include the
> object in there.
>
> Any advice on the best way to solve this problem would be appreciated.
>

Exactly how I would do it depends on the rest of the application. I
would probably derive my own button - never be afraid to subclass.

You could also generate the buttons IDs up front, and maintain a
mapping between the IDs and the channels, like so:

self.mapper = {}
for channel in self.channels:
    id = wx.NewId()
    self.mapper[id] = channel
    channelbutton = wx.Button(self, id=id, label=channel.getName())


def channelChanged(self, event):
    channel = self.mapper[event.Id]


You could also use closures (lambdas or via a factory function) to
bind the channel at the time you create the button:

for channel in self.channels:
    channelbutton = wx.Button(self, label=channel.getName())
    self.Bind(wx.EVT_BUTTON, lambda event:
self.channelChanged(channel), source=channelbutton)

def channelChanged(self, channel):
    print "Channel changed to ", channel.getName()



More information about the Python-list mailing list