Pagina 1 di 1

risolto - Tkinter - uso bottoni

Inviato: domenica 11 maggio 2014, 9:29
da maresama
Con:

Codice: Seleziona tutto

def prova(a):
    def clk(nn):
       print nn
       root.destroy()
    root =  Tk()
    n=0
    for rg in a:        
       n+=1
       lb2= Button(text=rg)
       lb2.bind("<Button-1>",lambda event: (event,clk(n)))
       lb2.pack()
    root.mainloop()

a=["aaa","bbb","ccc"]
prova(a)
qualunque bottone premo mi restituisce 3
Ma non dovrebbe darmi 1 o 2 o 3 secondo quale premo?
E come dovrei fare?
Tkinter mi sta alquanto antipatico.... (non lo capisco!)
Grazie.

Re: Tkinter - uso bottoni

Inviato: domenica 11 maggio 2014, 19:33
da maresama
e perchè così funziona?

Codice: Seleziona tutto

def prova(a):
    def clk(nn):
       print nn
       root.destroy()
    root =  Tk()
    rg=a[0]
    lb2= Button(text=rg)
    lb2.bind("<Button-1>",lambda event: (event,clk(1)))
    lb2.pack()
    rg=a[1]
    lb2= Button(text=rg)
    lb2.bind("<Button-1>",lambda event: (event,clk(2)))
    lb2.pack()
    rg=a[2]
    lb2= Button(text=rg)
    lb2.bind("<Button-1>",lambda event: (event,clk(3)))
    lb2.pack()
    root.mainloop()

a=["aaa","bbb","ccc"]
prova(a)
Qualcuno ci capisce qualcosa?

Re: Tkinter - uso bottoni

Inviato: lunedì 12 maggio 2014, 0:24
da Claudio_F
Porello Tkinter, è innocente... il tuo primo codice equivale esattamente a questo (ho solo tolto le espressioni lambda):

[code2=python]def prova(a):

def clk(nn):
print nn
root.destroy()

def anonima(event):
return event, clk(n)

root = Tk()
n = 0
for rg in a:
n += 1
lb2 = Button(text=rg)
lb2.bind("<Button-1>", anonima)
lb2.pack()
root.mainloop()

a = ["aaa", "bbb", "ccc"]
prova(a)[/code2]
Come si vede i pulsanti sono bindati solo alla funzione 'anonima', che a sua volta richiama 'clk' passando il valore di 'n' nel momento della chiamata (cioè sempre 3).

Il secondo codice invece non è traducibile in modo semplice, perché di fatto definisci tre funzioni anonime differenti (che chiamano clk con un argomento ben preciso).

In effetti quello del passaggio di valori alle callback è un argomento scomodo, si può risolvere bindando i widget a istanze chiamabili contenenti i dati voluti:

[code2=python]class Ponte:

def __init__(self, callback, nn):
self.callback = callback
self.nn = nn

def __call__(self, event):
self.callback(self.nn)


def prova(a):

def clk(nn):
print nn
root.destroy()

root = Tk()
n = 0
for rg in a:
n += 1
lb2 = Button(text=rg)
lb2.bind("<Button-1>", Ponte(clk, n))
lb2.pack()
root.mainloop()

a = ["aaa", "bbb", "ccc"]
prova(a)[/code2]
Oppure, se non si vuole usare una classe, si può anche usare una clojure:

[code2=python]def ponte(callback, nn):
def new_function(event):
callback(nn)
return new_function


def prova(a):

def clk(nn):
print nn
root.destroy()

root = Tk()
n = 0
for rg in a:
n += 1
lb2 = Button(text=rg)
lb2.bind("<Button-1>", ponte(clk, n))
lb2.pack()
root.mainloop()

a = ["aaa", "bbb", "ccc"]
prova(a)[/code2]

Re: Tkinter - uso bottoni

Inviato: lunedì 12 maggio 2014, 21:50
da maresama
Ti ringrazio, specialmente per le spiegazioni.
Seguito a dire che, per me, tkinter è ... antipatico!
Ho sempre digerito poco tutta la problematica delle callback per il binding.
Ma se uno capisce il problema... è come prendere un digestivo...!
Grazie nuovamente.
Ciao