Tkinter.Menu() Question

A

Adonis

I wish to create a popup menu from a list, when it is created they all show
the same label from the list:

Months = [0, 'January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November',
'December']

def _Menu_Click(self, month):
print month

menu = Menu(fraMain, tearoff=0)

for Month in Months[1:]:
menu.add_command(label=Month, command=lambda : _Menu_Click(Month))

When the menu calls _Menu_Click(...) it always prints 'December'

Now my understanding is the when an object is created and it is replicated,
whichever of the modified replications affects all of the objects, being
that they are just mere references to the original (my wording might be off,
correct me if I am wrong). How do I avoid this for what I am trying to
achieve?

Any help is greatly appreciated.

Adonis
 
P

Peter Otten

Adonis said:
I wish to create a popup menu from a list, when it is created they all
show the same label from the list:

Months = [0, 'January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November',
'December']

def _Menu_Click(self, month):
print month

menu = Menu(fraMain, tearoff=0)

for Month in Months[1:]:
menu.add_command(label=Month, command=lambda : _Menu_Click(Month))

When the menu calls _Menu_Click(...) it always prints 'December'

Now my understanding is the when an object is created and it is
replicated, whichever of the modified replications affects all of the
objects, being that they are just mere references to the original (my
wording might be off, correct me if I am wrong). How do I avoid this for
what I am trying to achieve?

(I made some bogus changes so I could ensure it works)

from Tkinter import *

Months = [0, 'January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November',
'December']

root = Tk()

class DontCare:
def _Menu_Click(self, month):
print month
dc = DontCare()

mb = Menubutton(root, text="so what")
mb.pack()
menu = mb["menu"] = Menu(mb, tearoff=0)


for Month in Months[1:]:
menu.add_command(label=Month, command=lambda m=Month: dc._Menu_Click(m))

root.mainloop()

Note how the instance (dc) is provided with the method (_Menu_Click) in the
lambda (in your real code you will most likely have to replace dc with
self). The real trick is to provide the loop variable Month as the default
value for m in the lambda. m will be bound to the same string as Month when
the lambda is *created*. If you don't do this, the value of the variable
Month will be looked up when the lambda is *called*, which will be always
"December" after the for loop is terminated.

Peter
 
A

Adonis

Peter Otten said:
Adonis said:
I wish to create a popup menu from a list, when it is created they all
show the same label from the list:

Months = [0, 'January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November',
'December']

def _Menu_Click(self, month):
print month

menu = Menu(fraMain, tearoff=0)

for Month in Months[1:]:
menu.add_command(label=Month, command=lambda : _Menu_Click(Month))

When the menu calls _Menu_Click(...) it always prints 'December'

Now my understanding is the when an object is created and it is
replicated, whichever of the modified replications affects all of the
objects, being that they are just mere references to the original (my
wording might be off, correct me if I am wrong). How do I avoid this for
what I am trying to achieve?

(I made some bogus changes so I could ensure it works)

from Tkinter import *

Months = [0, 'January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November',
'December']

root = Tk()

class DontCare:
def _Menu_Click(self, month):
print month
dc = DontCare()

mb = Menubutton(root, text="so what")
mb.pack()
menu = mb["menu"] = Menu(mb, tearoff=0)


for Month in Months[1:]:
menu.add_command(label=Month, command=lambda m=Month: dc._Menu_Click(m))

root.mainloop()

Note how the instance (dc) is provided with the method (_Menu_Click) in the
lambda (in your real code you will most likely have to replace dc with
self). The real trick is to provide the loop variable Month as the default
value for m in the lambda. m will be bound to the same string as Month when
the lambda is *created*. If you don't do this, the value of the variable
Month will be looked up when the lambda is *called*, which will be always
"December" after the for loop is terminated.

Peter

Thanks a million, works like a charm.

Adonis
 
J

John Grayson

Try:

for Month in Months[1:]:
menu.add_command(label=Month, command=lambda m=Month : \
_Menu_Click(m))
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top