2010-09-13 68 views
13

Estoy tratando de hacer un formulario de recuperación de compilación, y parece que tengo problemas con los botones ... Soy un novato en la programación de GUI de Python/tkinter (y programación de GUI en general) y tomé prestado el esqueleto de Hello World aplicación, y luego construyó eso.El comando del botón Tkinter se activa al ejecutar el programa?

En el siguiente código, he establecido la opción "comando" de mi botón Examinar para llamar a la función interna get_dir() de mi clase cuando se hace clic en ella. Sin embargo, tan pronto como intento ejecutar la aplicación, se llama a la función get_dir() y me piden que elija un directorio. ¿Alguna idea de por qué sucede esto y qué puedo hacer para que se comporte correctamente?

from Tkinter import * 
import tkFont 
from tkFileDialog import askdirectory 

class App: 

    def __init__(self, master): 

     fontHead = tkFont.Font(family="Arial", size=10, weight=tkFont.BOLD) 
     fontBold = tkFont.Font(family="Arial", size=8, weight=tkFont.BOLD) 
     fontReg = tkFont.Font(family="Arial", size=8) 

     frameN = Frame(master) 
     frameN.grid(row=0,padx=5,pady=5) 

     frameXBH = Frame(frameN) 
     frameXBH.grid(row=0,columnspan=5,padx=5) 

     Canvas(frameXBH,borderwidth=0,relief="flat",height=1,width=20,background="#cccccc").grid(row=0) 
     Label(frameXBH, text="Xbox 360",font=fontBold,width=9).grid(row=0,column=1) 
     Canvas(frameXBH,borderwidth=0,relief="flat",height=1,width=440,background="#cccccc").grid(row=0,column=2,sticky="WE") 

     Label(frameN, text="Destination Path:",font=fontReg).grid(row=1,sticky="W") 
     xbPath = Entry(frameN,width=30,font=fontReg) 
     xbPath.grid(row=1,column=1,sticky="W") 
     xbBrowse = Button(frameN,text="Browse...",font=fontReg,command=self.get_dir(xbPath)) 
     xbBrowse.grid(row=1,column=2,sticky="W") 
     xbRel = Checkbutton(frameN,text="Release",font=fontReg) 
     xbRel.grid(row=1,column=3,sticky="W") 
     xbShip = Checkbutton(frameN,text="Ship",font=fontReg) 
     xbShip.grid(row=1,column=4,sticky="W") 

     Canvas(frameN,borderwidth=1,relief="groove",width=550,height=0).grid(row=2,columnspan=5,pady=10) 

     # SAVE AND CANCEL 

     btnSave = Button(frameN,text="Save",width=10) 
     btnSave.grid(row=3,column=3,sticky="E") 

     btnCancel = Button(frameN,text="Cancel",width=10) 
     btnCancel.grid(row=3,column=4,sticky="W") 

    def get_dir(self,box): 
     tmp = askdirectory(mustexist=1,title="Please select a destination") 
     tmp = tmp.replace("/","\\") 
     box.delete(0,END) 
     box.insert(0,tmp) 

root = Tk() 
root.resizable(0,0) 

app = App(root) 

root.mainloop() 
+0

duplicado Posible de [¿Por qué el parámetro de botón "comando" se ejecuta cuando se declara?] (http://stackoverflow.com/questions/5767228/why-i s-botón-parámetro-comando-ejecutado-cuando-declarado) – nbro

+0

@nbro Creo que tiene su duplicado al revés, le pregunté esto en 2010, el que está marcando esto se le pidió un duplicado en 2011 -_- –

+0

razón por la que marqué esta publicación como un duplicado de la otra es porque la otra en realidad contiene más información y esa pregunta es más simple ... – nbro

Respuesta

17

hacer que su controlador de eventos en función lambda, que llama a su get_dir() con cualquier argumento que desee:

xbBrowse = Button(frameN, text="Browse...", font=fontReg, command=lambda : self.get_dir(xbPath)) 
+1

¿Puedes explicar qué está haciendo al agregar la parte lambda? Tuve este problema con la aplicación mínima en los documentos de Tkinter, donde quería agregar texto a la ventana cuando se presiona el botón.Tenía el comando = label.grid() añadiendo una etiqueta cuando se ejecutó, y al agregarla la solucioné. ¿Por qué el comando sin lambda se ejecutó de inmediato? ¿Qué está haciendo la palabra clave lambda? – Matt

5

En el código anterior:

xbBrowse = Button(frameN,text="Browse...",font=fontReg,command=self.get_dir(xbPath)) 

está invocando a la función ya, usted debe pasar simplemente la función:

xbBrowse = Button(frameN,text="Browse...",font=fontReg,command=self.get_dir) 
+0

¡Ah, ya veo! Ahora para descubrir cómo pasar parámetros a la función ... –

+1

@Doktor J: No necesita pasar una referencia a su xbPath, mire mi respuesta – volting

3

lo necesario para pasar una referencia de su get_dir método

así que cambie

xbBrowse = Button(frameN,text="Browse...",font=fontReg,command=self.get_dir(xbPath)) 

a

xbBrowse = Button(frameN,text="Browse...",font=fontReg, command=self.get_dir) 

A continuación, hacer su Entry widget de una variable de instancia para que pueda acceder a él en su método get_dir.

p. Ej.

self.xbPath = Entry(frameN,width=30,font=fontReg) 

A continuación, el método get_dir() se verá así:

def get_dir(self): 
    tmp = askdirectory(mustexist=1,title="Please select a destination") 
    tmp = tmp.replace("/","\\") 

    self.xbPath.delete(0,END) 
    self.xbPath.insert(0,tmp) 
+0

Tengo la intención de tener más de un botón de exploración/entrada en el aunque creo que necesito varios botones para llamar a get_dir() y pasarle el campo de entrada apropiado ... ¿cómo lo harías? –

+0

@Doktor J: la forma convencional de es tener un controlador separado para cada evento, por lo que en su caso, un método get_dir() separado para cada botón de exploración o, alternativamente, puede implementar su widget de botón de búsqueda + entrada + .. como widget compuesto y hacer que automáticamente haga todo lo que quiera, es decir, obtener un proceso de ruta, mostrarlo, etc. Entonces es tan simple como crear tantas instancias de sus widgets compuestos como desee. – volting

Cuestiones relacionadas