2011-08-21 10 views
5

Quiero agregar 10 botones a Tkinter, llamado One to Ten. Básicamente, simplemente usé el método de fuerza bruta, agregando cada botón a medida que avanzaba, en la función init de la clase de mi aplicación. Funciona, pero quiero minimizar el código utilizado, para ser más eficiente, como usar una estructura de datos para mantener todos los botones.¿Cómo puedo agregar muchos botones al marco tkinter de manera eficiente?

Estaba pensando en utilizar un buttonBox para mantener pulsados ​​todos los botones, pero no estaba seguro de poder manipular la ubicación mediante grid() para colocar los botones como quería.

self.one = Button(frame, text="One", command=self.callback) 
self.one.grid(sticky=W+E+N+S, padx=1, pady=1) 

self.two = Button(frame, text="Two", command=self.callback) 
self.two.grid(sticky=W+E+N+S, row=0, column=1, padx=1, pady=1) 

self.three = Button(frame, text="Three", command=self.callback) 
self.three.grid(sticky=W+E+N+S, row=0, column=2, padx=1, pady=1) 

# ... 

self.ten = Button(frame, text="Ten", command=self.callback) 
self.ten.grid(sticky=W+E+N+S, row=1, column=4, padx=1, pady=1) 

¿Alguien me puede mostrar una forma de hacer esto más eficiente, como una estructura de datos?

Respuesta

4

En lugar de nombrar los botones self.one, self.two, etc., sería más conveniente consultarlos indizando una lista, como self.button.

Si los botones son diferentes cosas, entonces solo tiene que explícitamente asociar botones con devoluciones de llamada. Por ejemplo:

name_callbacks=(('One',self.callback_one), 
       ('Two',self.callback_two), 
       ..., 
       ('Ten',self.callback_ten)) 
self.button=[] 
for i,(name,callback) in enumerate(name_callbacks): 
    self.button.append(Button(frame, text=name, command=callback)) 
    row,col=divmod(i,5) 
    self.button[i].grid(sticky=W+E+N+S, row=row, column=col, padx=1, pady=1) 

Si todos los botones hacen similares cosas, entonces una devolución de llamada puede ser suficiente para dar servicio a todos. Dado que la devolución de llamada en sí no puede tomar argumentos, se puede configurar una fábrica de devolución de llamada para pasar los argumentos a través de un cierre:

def callback(self,i): # This is the callback factory. Calling it returns a function. 
    def _callback(): 
     print(i) # i tells you which button has been pressed. 
    return _callback 

def __init__(self): 
    names=('One','Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten') 
    self.button=[] 
    for i,name in enumerate(names): 
     self.button.append(Button(frame, text=name, command=self.callback(i+1))) 
     row,col=divmod(i,5) 
     self.button[i].grid(sticky=W+E+N+S, row=row, column=col, padx=1, pady=1) 
+1

¡Gracias! Esto funcionó, pero tuve que cambiarlo a "self.button.append()" por lo que no causó un IndexError. Y la línea de fondo cambió a self.button [i] .grid(), en lugar de self.one.grid(). Funcionó perfectamente :) – thatbennyguy

+0

@thatbennyguy: ¡Ack! ¡Gracias por las correcciones! – unutbu

+0

Solo una cosa ... ¿Cómo obtendrías los botones para devolver diferentes comandos? – thatbennyguy

1

Se puede poner todos los botones de propiedades en un diccionario, y luego bucle en él para crear sus botones, aquí hay un ejemplo:

buttons = { 
    'one': {'sticky': W+E+N+S, 'padx': 1, 'pady': 1}, 
    'two': {'sticky': W+E+N+S, 'row': 0, 'column': 1, 'padx': 1, 'pady': 1}, 
    'three': {'sticky': W+E+N+S, 'row': 0, 'column': 2, 'padx': 1, 'pady': 1} 
} 
for b in buttons: 
    button = Button(frame, text=b.title(), command=self.callback) 
    button.grid(**buttons[b]) 
    setattr(self, b, button) 

Esto también le permitirá agregar fácilmente nuevos botones si es necesario.

Cuestiones relacionadas