2010-08-17 11 views
10

Desidero associare gli eventi automatici dopo le associazioni di classi di widget Text, al fine di modificare il testo del widget quando viene chiamata la funzione di associazione. Il mio binding, ad esempio self.text.bind("<Key>", self.callback), viene chiamato prima che il contenuto nel widget di Testo cambi.Come associare gli eventi di auto nel widget Testo di Tkinter dopo che sarà stato associato al widget Testo?

+0

Qual è il "solito problema" che si sta utilizzando? Si prega di mostrare qualche codice –

+0

self.text.bind ("", self.callback) – vladimar

+0

così all'inizio è chiamato self.callback e quindi questa chiave sarà digitata nel widget di testo – vladimar

risposta

20

Quello che sta accadendo nel tuo caso è che il tuo binding per stampare il valore avviene prima del binding della classe, ed è il binding di classe che in realtà prende l'input dell'utente e lo inserisce nel widget. Ci sono diversi modi per risolvere questo problema. È possibile eseguire il binding a <KeyRelease> anziché a <KeyPress> oppure è possibile utilizzare le funzionalità di convalida della voce incorporate per fare in modo che il codice venga richiamato ogni volta che si preme un tasto. Con questa soluzione ti verranno dati tutti i dati necessari: il valore prima della modifica, il valore dopo la modifica, il tasto premuto, ecc.

Un'altra scelta è quella di modificare l'ordine in cui gli eventi sono trasformati. Poiché la tua domanda ha chiesto in particolare come modificare l'ordine, questo è ciò che affronterò.

Anche se un'associazione sembra associata a un widget quando si esegue qualcosa come entry.bind(...), si sta effettivamente assegnando un'associazione a un "tag di bind" (o "bindtag"). Per impostazione predefinita, ogni widget ha un bindtag uguale al nome del widget. Altri bindtag includono la classe di un widget (ad esempio, "Entry"), il percorso della finestra di root (ad esempio: ".") E il tag speciale "all". Ai widget viene assegnato un insieme di bindtag che vengono elaborati in ordine quando viene ricevuto un evento. L'ordine predefinito va dalla maggior parte al meno specifico: widget, classe, toplevel, tutto.

Ci sono un paio di modi per manipolare i bindtag per ottenere il risultato desiderato. Una scelta è quella di riorganizzare l'ordine dei bindtag. Spostando il bindtag che rappresenta il widget che si trova dopo il bindtag che rappresenta la classe, la classe gestirà l'evento prima di passarlo al widget specifico.

Un'altra scelta consiste nell'aggiungere un ulteriore bindtag dopo il bind di classe e quindi inserire i bind in questo tag anziché nel tag che rappresenta il widget.

Perché scegliere l'uno rispetto all'altro? Riorganizzando l'ordine si influiranno su tutti i collegamenti su quel widget. Se si hanno molti collegamenti e alcuni dipendono dall'ordine (in modo che il contenitore, ad esempio, non consenta determinate sequenze di tasti), la modifica dell'ordine potrebbe causare il blocco di tali associazioni.

Introducendo un nuovo bindtag, è possibile scegliere quali associazioni avvengono prima delle associazioni di classi e quali succedono dopo.

Nel seguente codice creo tre widget di immissione. Il primo utilizza l'insieme predefinito di bindtag (impostato esplicitamente nell'esempio, sebbene siano identici al valore predefinito). Il secondo modifica l'ordine e il terzo introduce un ulteriore bindtag. Esegui il codice, quindi premi un tasto mentre lo stato attivo è in ciascuna finestra. Si noti che nel primo widget di immissione l'associazione sembra essere sempre un personaggio dietro. Ancora, questo perché il bind del widget avviene prima che il bind di classe inserisca il carattere nel widget.

Nel secondo e nel terzo esempio, l'associazione si verifica dopo il bind di classe in modo che la funzione visualizzi la modifica nei widget.

import Tkinter 

def OnKeyPress(event): 
    value = event.widget.get() 
    string="value of %s is '%s'" % (event.widget._name, value) 
    status.configure(text=string) 

root = Tkinter.Tk() 

entry1 = Tkinter.Entry(root, name="entry1") 
entry2 = Tkinter.Entry(root, name="entry2") 
entry3 = Tkinter.Entry(root, name="entry3") 

# Three different bindtags. The first is just the default but I'm 
# including it for illustrative purposes. The second reverses the 
# order of the first two tags. The third introduces a new tag after 
# the class tag. 
entry1.bindtags(('.entry1', 'Entry', '.', 'all')) 
entry2.bindtags(('Entry', '.entry2', '.', 'all')) 
entry3.bindtags(('.entry3','Entry','post-class-bindings', '.', 'all')) 

btlabel1 = Tkinter.Label(text="bindtags: %s" % " ".join(entry1.bindtags())) 
btlabel2 = Tkinter.Label(text="bindtags: %s" % " ".join(entry2.bindtags())) 
btlabel3 = Tkinter.Label(text="bindtags: %s" % " ".join(entry3.bindtags())) 
status = Tkinter.Label(anchor="w") 

entry1.grid(row=0,column=0) 
btlabel1.grid(row=0,column=1, padx=10, sticky="w") 
entry2.grid(row=1,column=0) 
btlabel2.grid(row=1,column=1, padx=10, sticky="w") 
entry3.grid(row=2,column=0) 
btlabel3.grid(row=2,column=1, padx=10) 
status.grid(row=3, columnspan=2, sticky="w") 

# normally you bind to the widget; in the third case we're binding 
# to the new bindtag we've created 
entry1.bind("<KeyPress>", OnKeyPress) 
entry2.bind("<KeyPress>", OnKeyPress) 
entry3.bind_class("post-class-bindings", "<KeyPress>", OnKeyPress) 

root.mainloop() 
+0

Sto provando a creare e associare un'associazione personalizzata a un widget 'Text', ma quando provo a scrivere su' Text', non posso, non succede nulla. Questo è il codice: 'self.tab1.text.bindtags (('. Tab1', 'Frame', 'n-binding', '.', 'All')) self.tab1.text.bind_class ('n -binding ',' ', self.bottom_bar.on_key_pressed) ' – nbro

+0

@nbro: sembra che tu abbia rimosso il bindtag di default' Testo', quindi nessun bind di widget di testo è associato al widget. –

Problemi correlati