GetEventObject() / wx.Menuitem woes.

Here I go trying to explain something… Pardon me in advance.

I can see the light at the end of the tunnel for this program I’ve been

working on for the past month + / -…

let’s say I have 2 instances of a button on a frame.

And those 2 buttons are bound to an event.

and I can reference the dictionary that each button resides in by a

line something like this:

button.Object = Dictionary-the-button-instance-is-in.

I have learned that this one event can distinguish which button

called it by having this line in event.

btn = event.GetEventObject()

so with that being said I can reference the dictionary full of goodies

by saying this:

print btn.Object

which would print everything in that dictionary. Or I could reference other

things in that dictionary specifically.

Ok… My woe…

Is there a way to the above with a wx.MenuItem. When I try it, it doesn’t

work. the result of GetEventObject is the wxFrame, not the actual menu item.

and the “Object” gives me an exception, saying that the wxFrame doesn’t have

an attribute called “Object”

It works with a button, but doesn’t with a menu item. But I want a menu item.

Thanks for the patience :stuck_out_tongue:

Steve

Have you tried with GetMenuId()?
Of course you have to take note beforehand of each menu ID.

···

2008/8/11 Steve Freedenburg stevefreedenburg@charter.net

Here I go trying to explain something… Pardon me in advance.

I can see the light at the end of the tunnel for this program I’ve been

working on for the past month + / -…

let’s say I have 2 instances of a button on a frame.

And those 2 buttons are bound to an event.

and I can reference the dictionary that each button resides in by a

line something like this:

button.Object = Dictionary-the-button-instance-is-in.

I have learned that this one event can distinguish which button

called it by having this line in event.

btn = event.GetEventObject()

so with that being said I can reference the dictionary full of goodies

by saying this:

print btn.Object

which would print everything in that dictionary. Or I could reference other

things in that dictionary specifically.

Ok… My woe…

Is there a way to the above with a wx.MenuItem. When I try it, it doesn’t

work. the result of GetEventObject is the wxFrame, not the actual menu item.

and the “Object” gives me an exception, saying that the wxFrame doesn’t have

an attribute called “Object”

It works with a button, but doesn’t with a menu item. But I want a menu item.

Thanks for the patience :stuck_out_tongue:

Steve


wxpython-users mailing list

wxpython-users@lists.wxwidgets.org

http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

Well each item is an instance, so the ID will be wx.ID_ANY or -1. Today I may have 4 menu items,

the next time I use the program I may have 6 menu items, it just depends on how the program is used.

···

----- Original Message -----

From:
raffaello

To: wxpython-users@lists.wxwidgets.org

Sent: Monday, 11 August, 2008 00:51

Subject: Re: [wxpython-users] GetEventObject() / wx.Menuitem woes.

Have you tried with GetMenuId()?
Of course you have to take note beforehand of each menu ID.

2008/8/11 Steve Freedenburg stevefreedenburg@charter.net

Here I go trying to explain something...  Pardon me in advance.
I can see the light at the end of the tunnel for this program I've been
working on for the past month + / -...
let's say I have 2 instances of a button on a frame.
And those 2 buttons are bound to an event.
and I can reference the dictionary that each button resides in by a

line something like this:

button.Object = Dictionary-the-button-instance-is-in.
I have learned that this one event can distinguish which button
called it by having this line in event.

btn = event.GetEventObject()

so with that being said I can reference the dictionary full of goodies

by saying this:

print btn.Object

which would print everything in that dictionary.  Or I could reference other
things in that dictionary specifically.

Ok… My woe…

Is there a way to the above with a wx.MenuItem.  When I try it, it doesn't

work. the result of GetEventO bject is the wxFrame, not the actual menu item.

and the "Object" gives me an exception, saying that the wxFrame doesn't have

an attribute called “Object”

It works with a button, but doesn't with a menu item.  But I want a menu item.

Thanks for the patience :stuck_out_tongue:

Steve


wxpython-users mailing list

wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users



wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

wx.ID_ANY or -1 simply mean that you accept an ID whatever assigned by wx.Python. But there is however a specific ID, the only problem is to know it.
You can either use id = wx.NewId() and then assign id to the constructor of your wx.MenuItem instead of wx.ID_ ANY, or build your wx.MenuItem as you used to do, and then extract the id with GetId().

Trust, anyway, that that ID will be unique: wx.Python works with IDs, not names.

···

2008/8/11 Steve Freedenburg stevefreedenburg@charter.net

Well each item is an instance, so the ID will be wx.ID_ANY or -1. Today I may have 4 menu items,

the next time I use the program I may have 6 menu items, it just depends on how the program is used.

----- Original Message -----

From:
raffaello

To: wxpython-users@lists.wxwidgets.org

Sent: Monday, 11 August, 2008 00:51

Subject: Re: [wxpython-users] GetEventObject() / wx.Menuitem woes.

Have you tried with GetMenuId()?
Of course you have to take note beforehand of each menu ID.

2008/8/11 Steve Freedenburg stevefreedenburg@charter.net

Here I go trying to explain something...  Pardon me in advance.
I can see the light at the end of the tunnel for this program I've been
working on for the past month + / -...
let's say I have 2 instances of a button on a frame.
And those 2 buttons are bound to an event.
and I can reference the dictionary that each button resides in by a

line something like this:

button.Object = Dictionary-the-button-instance-is-in.
I have learned that this one event can distinguish which button
called it by having this line in event.

btn = event.GetEventObject()

so with that being said I can reference the dictionary full of goodies

by saying this:

print btn.Object

which would print everything in that dictionary.  Or I could reference other
things in that dictionary specifically.

Ok… My woe…

Is there a way to the above with a wx.MenuItem.  When I try it, it doesn't

work. the result of GetEventO bject is the wxFrame, not the actual menu item.

and the "Object" gives me an exception, saying that the wxFrame doesn't have

an attribute called “Object”

It works with a button, but doesn't with a menu item.  But I want a menu item.

Thanks for the patience :stuck_out_tongue:

Steve


wxpython-users mailing list

wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users



wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users


wxpython-users mailing list

wxpython-users@lists.wxwidgets.org

http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

Steve Freedenburg wrote:

Well each item is an instance, so the ID will be wx.ID_ANY or -1. Today I may have 4 menu items,
the next time I use the program I may have 6 menu items, it just depends on how the program is used.

Why aren't you able to set the menu item ids as you create the 4 or 6 menu items? Just number them starting at 1 as they get created.

I tried that out, the result is odd.

My original code:
<CODE>

for Item in self.ContSettings:
    ContLabel = Item['Label']
    Item['MenuItem'] = wx.MenuItem(self.TopiView, wx.ID_ANY, ContLabel, '')
    self.Containers.AppendItem(Item['MenuItem'])
    self.Bind(wx.EVT_MENU, self.OnContainerClick, Item['MenuItem'])

def OnContainerClick(self, event):
    obj = event.GetId()
    print obj
    event.Skip()

</CODE>
The result of of the function prints the ID one time in IDLE, thus
telling me the event happened one time when the menu item was
clicked.

104
105

AND.

Setting the ID's myself:
<CODE>

qty = 0
for Item in self.ContSettings:
    x = qty + 1
    ContLabel = Item['Label']
    Item['MenuItem'] = wx.MenuItem(self.TopiView, x, ContLabel, '')
    self.Containers.AppendItem(Item['MenuItem'])
    self.Bind(wx.EVT_MENU, self.OnContainerClick, Item['MenuItem'])

def OnContainerClick(self, event):
    obj = event.GetId()
    print obj
    event.Skip()
</CODE>

The only thing that is diferent is that I've set the ID for menu item starting at
1, then the next is 2 so on and so forth.

What happens is it "seems" like the event happens twice with one click of
the menu item.

1
2

···

----- Original Message ----- From: "Samwyse" <samwyse@gmail.com>
To: <wxpython-users@lists.wxwidgets.org>
Sent: Monday, 11 August, 2008 02:07
Subject: [wxpython-users] Re: GetEventObject() / wx.Menuitem woes.

Steve Freedenburg wrote:

Well each item is an instance, so the ID will be wx.ID_ANY or -1. Today I may have 4 menu items,
the next time I use the program I may have 6 menu items, it just depends on how the program is used.

Why aren't you able to set the menu item ids as you create the 4 or 6 menu items? Just number them starting at 1 as they get created.

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

The objective is to be able to reference specific dictionaries in the list called
self.ContSettings. I guess I don't have to use a pull down menu. wx.Button
will do exactly what I want it to do, but each represents it's own problem.
with wx.MenuItem, I can't "GetEventObject()" like I can with a wx.Button
which returns the actuall button, while wx.MenuItem returns the wxFrame.

With the wx.Button getting the items into sizers according to the shape of
the frame the buttons are in would be a challenge. While a MenuItem simply
gets added to the Menu.

Argh! Scurvy program!

···

----- Original Message ----- From: "Steve Freedenburg" <stevefreedenburg@charter.net>
To: <wxpython-users@lists.wxwidgets.org>
Sent: Monday, 11 August, 2008 07:48
Subject: Re: [wxpython-users] Re: GetEventObject() / wx.Menuitem woes.

I tried that out, the result is odd.

My original code:
<CODE>

for Item in self.ContSettings:
   ContLabel = Item['Label']
   Item['MenuItem'] = wx.MenuItem(self.TopiView, wx.ID_ANY, ContLabel, '')
   self.Containers.AppendItem(Item['MenuItem'])
   self.Bind(wx.EVT_MENU, self.OnContainerClick, Item['MenuItem'])

def OnContainerClick(self, event):
   obj = event.GetId()
   print obj
   event.Skip()

</CODE>
The result of of the function prints the ID one time in IDLE, thus
telling me the event happened one time when the menu item was
clicked.

104
105

AND.

Setting the ID's myself:
<CODE>

qty = 0
for Item in self.ContSettings:
   x = qty + 1
   ContLabel = Item['Label']
   Item['MenuItem'] = wx.MenuItem(self.TopiView, x, ContLabel, '')
   self.Containers.AppendItem(Item['MenuItem'])
   self.Bind(wx.EVT_MENU, self.OnContainerClick, Item['MenuItem'])

def OnContainerClick(self, event):
   obj = event.GetId()
   print obj
   event.Skip()
</CODE>

The only thing that is diferent is that I've set the ID for menu item starting at
1, then the next is 2 so on and so forth.

What happens is it "seems" like the event happens twice with one click of
the menu item.

1
2

----- Original Message ----- From: "Samwyse" <samwyse@gmail.com>
To: <wxpython-users@lists.wxwidgets.org>
Sent: Monday, 11 August, 2008 02:07
Subject: [wxpython-users] Re: GetEventObject() / wx.Menuitem woes.

Steve Freedenburg wrote:

Well each item is an instance, so the ID will be wx.ID_ANY or -1. Today I may have 4 menu items,
the next time I use the program I may have 6 menu items, it just depends on how the program is used.

Why aren't you able to set the menu item ids as you create the 4 or 6 menu items? Just number them starting at 1 as they get created.

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

Update:
Some success, yet I'm not sure how to make the Item['MenuItem'] visible to other
functions. See...

<CODE>
for Item in self.ContSettings:
    x = qty + 1
    ContLabel = Item['Label']
    Item['MenuItem'] = wx.MenuItem(self.TopiView, wx.ID_ANY, ContLabel, '')
    Item['MenuItem'].Object = Item
    Containers.AppendItem(Item['MenuItem'])
    self.Bind(wx.EVT_MENU, self.OnContainerClick, Item['MenuItem'])

def OnContainerClick(self, event):
    ItemId = event.GetId()
    Cont = self.Containers.FindItemById(ItemId)
    Label = self.Containers.GetLabel(ItemId)
    print ItemId
    print Cont
    print Label
    print Cont.Object
    event.Skip()

</CODE>
The statement "print Cont.Object" tells me in IDLE:
AttributeError: 'MenuItem' object has no attribute 'Object'

Is this because it doesn't belong to the frame? no self. ??

···

----- Original Message ----- From: "Steve Freedenburg" <stevefreedenburg@charter.net>
To: <wxpython-users@lists.wxwidgets.org>
Sent: Monday, 11 August, 2008 07:57
Subject: Re: [wxpython-users] Re: GetEventObject() / wx.Menuitem woes.

The objective is to be able to reference specific dictionaries in the list called
self.ContSettings. I guess I don't have to use a pull down menu. wx.Button
will do exactly what I want it to do, but each represents it's own problem.
with wx.MenuItem, I can't "GetEventObject()" like I can with a wx.Button
which returns the actuall button, while wx.MenuItem returns the wxFrame.

With the wx.Button getting the items into sizers according to the shape of
the frame the buttons are in would be a challenge. While a MenuItem simply
gets added to the Menu.

Argh! Scurvy program!
----- Original Message ----- From: "Steve Freedenburg" <stevefreedenburg@charter.net>
To: <wxpython-users@lists.wxwidgets.org>
Sent: Monday, 11 August, 2008 07:48
Subject: Re: [wxpython-users] Re: GetEventObject() / wx.Menuitem woes.

I tried that out, the result is odd.

My original code:
<CODE>

for Item in self.ContSettings:
   ContLabel = Item['Label']
   Item['MenuItem'] = wx.MenuItem(self.TopiView, wx.ID_ANY, ContLabel, '')
   self.Containers.AppendItem(Item['MenuItem'])
   self.Bind(wx.EVT_MENU, self.OnContainerClick, Item['MenuItem'])

def OnContainerClick(self, event):
   obj = event.GetId()
   print obj
   event.Skip()

</CODE>
The result of of the function prints the ID one time in IDLE, thus
telling me the event happened one time when the menu item was
clicked.

104
105

AND.

Setting the ID's myself:
<CODE>

qty = 0
for Item in self.ContSettings:
   x = qty + 1
   ContLabel = Item['Label']
   Item['MenuItem'] = wx.MenuItem(self.TopiView, x, ContLabel, '')
   self.Containers.AppendItem(Item['MenuItem'])
   self.Bind(wx.EVT_MENU, self.OnContainerClick, Item['MenuItem'])

def OnContainerClick(self, event):
   obj = event.GetId()
   print obj
   event.Skip()
</CODE>

The only thing that is diferent is that I've set the ID for menu item starting at
1, then the next is 2 so on and so forth.

What happens is it "seems" like the event happens twice with one click of
the menu item.

1
2

----- Original Message ----- From: "Samwyse" <samwyse@gmail.com>
To: <wxpython-users@lists.wxwidgets.org>
Sent: Monday, 11 August, 2008 02:07
Subject: [wxpython-users] Re: GetEventObject() / wx.Menuitem woes.

Steve Freedenburg wrote:

Well each item is an instance, so the ID will be wx.ID_ANY or -1. Today I may have 4 menu items,
the next time I use the program I may have 6 menu items, it just depends on how the program is used.

Why aren't you able to set the menu item ids as you create the 4 or 6 menu items? Just number them starting at 1 as they get created.

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

Samwyse wrote:

<div class="moz-text-flowed" style="font-family: -moz-fixed">Steve Freedenburg wrote:

Well each item is an instance, so the ID will be wx.ID_ANY or -1. Today I may have 4 menu items,
the next time I use the program I may have 6 menu items, it just depends on how the program is used.

Why aren't you able to set the menu item ids as you create the 4 or 6 menu items? Just number them starting at 1 as they get created.

I don't recommend this if you end up using more than than a handful of ids. If you create duplicate ids, you'll probably get weird event handling. There's also the chance that you might dupe predefined constants. According to The Book, you should use wx.RegisterId() to ensure that an explicit ID doesn't get used by wx elsewhere in your program. It also says you can get the global constants by getting wx.ID_LOWEST and wx.ID_HIGHEST.

Just an FYI.

Mike

Steve Freedenburg wrote:

Here I go trying to explain something... Pardon me in advance.
I can see the light at the end of the tunnel for this program I've been
working on for the past month + / -...
let's say I have 2 instances of a button on a frame.
And those 2 buttons are bound to an event.
and I can reference the dictionary that each button resides in by a
line something like this:
button.Object = Dictionary-the-button-instance-is-in.
I have learned that this one event can distinguish which button
called it by having this line in event.
btn = event.GetEventObject()
so with that being said I can reference the dictionary full of goodies
by saying this:
print btn.Object
which would print everything in that dictionary. Or I could reference other
things in that dictionary specifically.
Ok... My woe...
Is there a way to the above with a wx.MenuItem. When I try it, it doesn't
work. the result of GetEventObject is the wxFrame, not the actual menu item.
and the "Object" gives me an exception, saying that the wxFrame doesn't have
an attribute called "Object"
It works with a button, but doesn't with a menu item. But I want a menu item.
Thanks for the patience :stuck_out_tongue:
Steve

I looked at how Robin's book did this sort of thing and came up with the following based on his code:

<code>

import wx
class MyForm(wx.Frame):
     def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "wx.Menu Tutorial")

        def doBind(item, handler):
            """ Create menu events. """
            self.Bind(wx.EVT_MENU, handler, item)
         # Add a panel so it looks the correct on all platforms
        self.panel = wx.Panel(self, wx.ID_ANY)
         menuBar = wx.MenuBar()
        fileMenu = wx.Menu()
               doBind(fileMenu.Append(wx.ID_ANY, "&Open\tCtrl+O", "OpenItem"),
               self.onEvent)
               doBind(fileMenu.Append(wx.ID_ANY, "&Exit\tAlt+F4", "ExitProgram"),
               self.onEvent)

        menuBar.Append(fileMenu, "&File")
        self.SetMenuBar(menuBar)
     def onEvent(self, event):
        item = self.GetMenuBar().FindItemById(event.GetId())
        text = item.GetText()
        wx.MessageBox("You selected the '%s' item" % text)
        # Run the program
if __name__ == "__main__":
    app = wx.PySimpleApp()
    frame = MyForm().Show()
    app.MainLoop()

</code>

Notice the GetMenuBar() and FindItemById() methods. You'll probably also like the FindMenuItem() method (which I'm not using) helpful.

···

-------------------
Mike Driscoll

Blog: http://blog.pythonlibrary.org
Python Extension Building Network: http://www.pythonlibrary.org

Steve Freedenburg wrote:

Is there a way to the above with a wx.MenuItem. When I try it, it doesn't
work. the result of GetEventObject is the wxFrame, not the actual menu item.

I forgot about this earlier in the thread, but this is a good reason NOT to use the technique of attaching your data object to the button itself. As I think about it, that should have been obvious -- really, the button is there to activate something, the data is not a property of the button (or the menu, or...)

So what to do?

I like using the "lambda trick" to pass data along to a callback:

TheButton.Bind(EVT_BUTTON,
               lambda evt, data=TheDataDict: self.TheCallBack(evt, data)
               )

Now your call back looks like:

def TheCallBack(evt, data):
     # do whatever you want with the data

You can do that same with menus:

item = MenuItem()
self.Bind(EVT_MENU,
           lambda evt, data=TheDataDict: self.TheCallBack(evt, data),
           item)

(untested code...)

How does this work:

lambda creates a function. so, in this case:

"lambda evt, data=TheDataDict"

creates a function that takes two arguments, evt, and data. Here is the nifty trick -- callbacks are supposed to be a function that takes one argument -- the event. So we make data a keyword argument with a default, so it can be called without giving that argument. The keyword arg default is evaluated when the function is defined, so it gets the value it has there. Here's an example to test that.

>>> def TestFun(x):
... print x
...
>>> FunList =
>>> for i in range(10):
... FunList.append(lambda y=i: TestFun(y))
...

>>> for f in FunList:
... f()
...
0
1
2
3
4
5
6
7
8
9

pretty cool huh?

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

I haven't tried to use the example below in what I'm doing.
I'm going to in about 3 minutes... It looks like it's exactly what
I need. In fact I'm almost scared to try it because I'll need
an intervention if it doesn't. Call Python EMS if you don't
hear from me soon.

···

----- Original Message ----- From: "Christopher Barker" <Chris.Barker@noaa.gov>
To: <wxpython-users@lists.wxwidgets.org>
Sent: Monday, 11 August, 2008 13:24
Subject: Re: [wxpython-users] GetEventObject() / wx.Menuitem woes.

Steve Freedenburg wrote:

Is there a way to the above with a wx.MenuItem. When I try it, it doesn't
work. the result of GetEventObject is the wxFrame, not the actual menu item.

I forgot about this earlier in the thread, but this is a good reason NOT to use the technique of attaching your data object to the button itself. As I think about it, that should have been obvious -- really, the button is there to activate something, the data is not a property of the button (or the menu, or...)

So what to do?

I like using the "lambda trick" to pass data along to a callback:

TheButton.Bind(EVT_BUTTON,
              lambda evt, data=TheDataDict: self.TheCallBack(evt, data)
              )

Now your call back looks like:

def TheCallBack(evt, data):
    # do whatever you want with the data

You can do that same with menus:

item = MenuItem()
self.Bind(EVT_MENU,
          lambda evt, data=TheDataDict: self.TheCallBack(evt, data),
          item)

(untested code...)

How does this work:

lambda creates a function. so, in this case:

"lambda evt, data=TheDataDict"

creates a function that takes two arguments, evt, and data. Here is the nifty trick -- callbacks are supposed to be a function that takes one argument -- the event. So we make data a keyword argument with a default, so it can be called without giving that argument. The keyword arg default is evaluated when the function is defined, so it gets the value it has there. Here's an example to test that.

>>> def TestFun(x):
... print x
...
>>> FunList =
>>> for i in range(10):
... FunList.append(lambda y=i: TestFun(y))
...

>>> for f in FunList:
... f()
...
0
1
2
3
4
5
6
7
8
9

pretty cool huh?

-Chris

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov
_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

You sir are a golden god.....

I will not cheapen the compliment I have given with much more than this:

Once again you have saved me considerable time, and make me regret not
coming to this mailing list sooner.

···

----- Original Message ----- From: "Christopher Barker" <Chris.Barker@noaa.gov>
To: <wxpython-users@lists.wxwidgets.org>
Sent: Monday, 11 August, 2008 13:24
Subject: Re: [wxpython-users] GetEventObject() / wx.Menuitem woes.

Steve Freedenburg wrote:

Is there a way to the above with a wx.MenuItem. When I try it, it doesn't
work. the result of GetEventObject is the wxFrame, not the actual menu item.

I forgot about this earlier in the thread, but this is a good reason NOT to use the technique of attaching your data object to the button itself. As I think about it, that should have been obvious -- really, the button is there to activate something, the data is not a property of the button (or the menu, or...)

So what to do?

I like using the "lambda trick" to pass data along to a callback:

TheButton.Bind(EVT_BUTTON,
              lambda evt, data=TheDataDict: self.TheCallBack(evt, data)
              )

Now your call back looks like:

def TheCallBack(evt, data):
    # do whatever you want with the data

You can do that same with menus:

item = MenuItem()
self.Bind(EVT_MENU,
          lambda evt, data=TheDataDict: self.TheCallBack(evt, data),
          item)

(untested code...)

How does this work:

lambda creates a function. so, in this case:

"lambda evt, data=TheDataDict"

creates a function that takes two arguments, evt, and data. Here is the nifty trick -- callbacks are supposed to be a function that takes one argument -- the event. So we make data a keyword argument with a default, so it can be called without giving that argument. The keyword arg default is evaluated when the function is defined, so it gets the value it has there. Here's an example to test that.

>>> def TestFun(x):
... print x
...
>>> FunList =
>>> for i in range(10):
... FunList.append(lambda y=i: TestFun(y))
...

>>> for f in FunList:
... f()
...
0
1
2
3
4
5
6
7
8
9

pretty cool huh?

-Chris

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov
_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

I didn't mean to send that last e-mail... It was just something I
typed out, and was going to erase it... I was just happy to see
more progress, and got a little carried away.

Anyhow. The disclaimer was needed :stuck_out_tongue: The code didn't work
as it was.

self.Bind(wx.EVT_MENU, lambda event, data=TheDataDict: self.TheCallBack(event, data),
item)

the callback function is missing something, it may take two arguments, and suposed to only
take one, but it doesn't work unless you add self as an arguement.

def TheCallBack(self, event, data):
not
def TheCallBack(event, data):

···

----- Original Message ----- From: "Christopher Barker" <Chris.Barker@noaa.gov>
To: <wxpython-users@lists.wxwidgets.org>
Sent: Monday, 11 August, 2008 13:24
Subject: Re: [wxpython-users] GetEventObject() / wx.Menuitem woes.

Steve Freedenburg wrote:

Is there a way to the above with a wx.MenuItem. When I try it, it doesn't
work. the result of GetEventObject is the wxFrame, not the actual menu item.

I forgot about this earlier in the thread, but this is a good reason NOT to use the technique of attaching your data object to the button itself. As I think about it, that should have been obvious -- really, the button is there to activate something, the data is not a property of the button (or the menu, or...)

So what to do?

I like using the "lambda trick" to pass data along to a callback:

TheButton.Bind(EVT_BUTTON,
              lambda evt, data=TheDataDict: self.TheCallBack(evt, data)
              )

Now your call back looks like:

def TheCallBack(evt, data):
    # do whatever you want with the data

You can do that same with menus:

item = MenuItem()
self.Bind(EVT_MENU,
          lambda evt, data=TheDataDict: self.TheCallBack(evt, data),
          item)

(untested code...)

How does this work:

lambda creates a function. so, in this case:

"lambda evt, data=TheDataDict"

creates a function that takes two arguments, evt, and data. Here is the nifty trick -- callbacks are supposed to be a function that takes one argument -- the event. So we make data a keyword argument with a default, so it can be called without giving that argument. The keyword arg default is evaluated when the function is defined, so it gets the value it has there. Here's an example to test that.

>>> def TestFun(x):
... print x
...
>>> FunList =
>>> for i in range(10):
... FunList.append(lambda y=i: TestFun(y))
...

>>> for f in FunList:
... f()
...
0
1
2
3
4
5
6
7
8
9

pretty cool huh?

-Chris

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov
_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users