Tengo un menú que, al hacer clic, debe mostrar un menú que contiene una secuencia específica de cadenas. Exactamente qué cadenas están en esa secuencia, no lo sabemos hasta el tiempo de ejecución, por lo que el menú que aparece debe generarse en ese momento. Aquí es lo que tengo:Creación dinámica de un menú en Tkinter. (¿expresiones lambda?)
class para_frame(Frame):
def __init__(self, para=None, *args, **kwargs):
# ...
# menu button for adding tags that already exist in other para's
self.add_tag_mb = Menubutton(self, text='Add tags...')
# this menu needs to re-create itself every time it's clicked
self.add_tag_menu = Menu(self.add_tag_mb,
tearoff=0,
postcommand = self.build_add_tag_menu)
self.add_tag_mb['menu'] = self.add_tag_menu
# ...
def build_add_tag_menu(self):
self.add_tag_menu.delete(0, END) # clear whatever was in the menu before
all_tags = self.get_article().all_tags()
# we don't want the menu to include tags that already in this para
menu_tags = [tag for tag in all_tags if tag not in self.para.tags]
if menu_tags:
for tag in menu_tags:
def new_command():
self.add_tag(tag)
self.add_tag_menu.add_command(label = tag,
command = new_command)
else:
self.add_tag_menu.add_command(label = "<No tags>")
La parte importante es lo que hay debajo "si menu_tags:" - menu_tags supongo que es la lista [ 'pila', 'más', 'flujo']. Entonces lo que yo quiero hacer es efectivamente esto:
self.add_tag_menu.add_command(label = 'stack', command = add_tag_stack)
self.add_tag_menu.add_command(label = 'over', command = add_tag_over)
self.add_tag_menu.add_command(label = 'flow', command = add_tag_flow)
donde add_tag_stack() se define como:
def add_tag_stack():
self.add_tag('stack')
y así sucesivamente.
El problema es que la variable 'etiqueta' toma el valor 'pila' y luego el valor 'sobre' y así sucesivamente, y no se evalúa hasta que se invoca new_command, en cuyo momento la variable 'etiqueta 'es solo' flujo '. Entonces, la etiqueta que se agrega siempre es la última en el menú, sin importar en qué haga clic el usuario.
Originalmente estaba usando una lambda, y pensé que quizás definir explícitamente la función anterior podría funcionar mejor. De cualquier manera, el problema ocurre. Intenté usar una copia de la variable 'etiqueta' (ya sea con "current_tag = tag" o usando el módulo de copia) pero eso no lo resuelve. No estoy seguro por qué.
Mi mente está empezando a vagar hacia cosas como "eval" pero espero que alguien pueda pensar de una manera inteligente que no involucre cosas tan horribles.
Muchas gracias!
(En caso de que sea relevante, Tkinter .__ version__ devuelve '$ Revision: 67083 $' y estoy usando Python 2.6.1 en Windows XP.)
Bueno, pensé que podría haber una solución específica para Tkinter. Alguien que diga "No, no, no, la forma en que haces esto es la función especial Tkinter.somethingOrOther()" ¡Gracias por la ayuda! – MatrixFrog
¡Ningún problema! Solo quería señalar que un buen primer paso es tratar de aislar un pequeño ejemplo del problema, para ver si se trata de un problema de lenguaje o de API. –