2013-03-12 7 views
5

Mi chiedo come associare più widget con un "binding".Come associare più widget con un "binding" in Tkinter?

Per expample:

ho tre pulsanti e voglio cambiare il loro colore dopo in bilico.

from Tkinter import * 

def SetColor(event): 
    event.widget.config(bg="red") 
    return 

def ReturnColor(event): 
    event.widget.config(bg="white") 
    return 

root = Tk() 

B1 = Button(root,text="Button 1", bg="white") 
B1.pack() 

B2 = Button(root, text="Button2", bg="white") 
B2.pack() 

B3 = Button(root, text= "Button 3", bg="white") 
B3.pack() 

B1.bind("<Enter>",SetColor) 
B2.bind("<Enter>",SetColor) 
B3.bind("<Enter>",SetColor) 

B1.bind("<Leave>",ReturnColor) 
B2.bind("<Leave>",ReturnColor) 
B3.bind("<Leave>",ReturnColor) 

root.mainloop() 

E il mio obiettivo è quello di avere solo due binding (per "Enter" e "Leave" eventi) invece di sei come sopra.

Grazie per tutte le idee

risposta

5

fare la stessa cosa a più oggetti? Mi sembra un ciclo for.

for b in [B1, B2, B3]: 
    b.bind("<Enter>", SetColor) 
    b.bind("<Leave>", ReturnColor) 

Si potrebbe andare oltre e tutto astratta del frammento:

for s in ["button 1", "button 2", "button 3"]: 
    b=Button(root, text=s, bg="white") 
    b.pack() 
    b.bind("<Enter>", SetColor) 
    b.bind("<Leave>", ReturnColor) 

Ora è facile aggiungere pulsanti aggiuntivi (basta aggiungere un'altra voce all'elenco di ingresso). È anche facile cambiare ciò che fai a tutti i pulsanti cambiando il corpo del ciclo for.

+0

Inoltre, è possibile impostare i parametri utilizzando un dizionario nidificato: 'bParams = {'button1': {'bg': 'red', 'command' = self.frame.quit, ...}, ... } '.Non sono sicuro di poter aggiungere i comandi nel dizionario, ma in caso contrario, puoi fare: 'b = Button (root, text = s, bg = bParams [b], ...)'. –

+0

Oh, grazie. Potrebbe funzionare :) –

6

Per rispondere alla domanda specifica sull'opportunità di applicare una singola associazione a più widget, la risposta è sì. Probabilmente produrrà più linee di codice piuttosto che meno, ma è facile da fare.

Tutti i widget tkinter hanno qualcosa chiamato "bindtag". Bindtag sono un elenco di "tag" a cui sono allegati i binding. Lo usi sempre senza saperlo. Quando esegui il binding a un widget, l'associazione non si trova effettivamente sul widget di per sé, ma su un tag che ha lo stesso nome del nome di livello basso del widget. I bind predefiniti si trovano su un tag che ha lo stesso nome della classe widget (la classe sottostante, non necessariamente la classe python). E quando chiami bind_all, sei vincolato al tag "all".

La cosa grandiosa dei bindtag è che è possibile aggiungere e rimuovere i tag tutto ciò che si desidera. Quindi, è possibile aggiungere il proprio tag e quindi assegnare il binding ad esso con bind_class (non so perché gli autori di Tkinter abbiano scelto quel nome ...).

Una cosa importante da ricordare è che i bindtag hanno un ordine e gli eventi vengono gestiti in questo ordine. Se un gestore eventi restituisce la stringa "break", la gestione degli eventi si interrompe prima che i bindtags rimanenti siano stati controllati per le associazioni.

Il risultato pratico di questo è, se vuoi che altri binding siano in grado di ignorare questi nuovi binding, aggiungi il tuo bindtag alla fine. Se vuoi che i tuoi attacchi siano impossibili da sovrascrivere da altri binding, mettilo all'inizio.

Esempio

import Tkinter as tk 

class Example(tk.Frame): 
    def __init__(self, *args, **kwargs): 
     tk.Frame.__init__(self, *args, **kwargs) 

     # add bindings to a new tag that we're going to be using 
     self.bind_class("mytag", "<Enter>", self.on_enter) 
     self.bind_class("mytag", "<Leave>", self.on_leave) 

     # create some widgets and give them this tag 
     for i in range(5): 
      l = tk.Label(self, text="Button #%s" % i, background="white") 
      l.pack(side="top") 
      new_tags = l.bindtags() + ("mytag",) 
      l.bindtags(new_tags) 

    def on_enter(self, event): 
     event.widget.configure(background="bisque") 

    def on_leave(self, event): 
     event.widget.configure(background="white") 

if __name__ == "__main__": 
    root = tk.Tk() 
    view = Example() 
    view.pack(side="top", fill="both", expand=True) 
    root.mainloop() 

un po 'più informazioni su bindtags può essere trovato in questa risposta: https://stackoverflow.com/a/11542200/7432

Inoltre, il metodo bindtags in sé è documentato nella pagina effbot Basic Widget Methods tra gli altri luoghi.