2010-08-17 3 views
10

Ich möchte Self-Ereignisse nach Widget Klassenbindungen binden, um den Text des Widgets zu ändern, wenn meine Bindungsfunktion aufgerufen wird. Meine Bindung, zum Beispiel self.text.bind("<Key>", self.callback), wird aufgerufen, bevor sich der Inhalt im Text-Widget ändert.Wie binden Sie Self-Events in das Tkinter Text-Widget, nachdem es vom Text-Widget gebunden wurde?

+0

Was ist die übliche Bindung, die Sie verwenden? Bitte zeigen einige Code –

+0

self.text.bind („“, self.callback) – vladimar

+0

so zuerst genannt self.callback wird und dann diese Taste wird in Text-Widget eingegeben – vladimar

Antwort

20

In Ihrem Fall geschieht Ihre Bindung zum Drucken des Werts vor der Klassenbindung, und es ist die Klassenbindung, die tatsächlich Benutzereingaben nimmt und sie in das Widget einfügt. Es gibt mehrere Möglichkeiten, dieses Problem zu lösen. Sie könnten an <KeyRelease> anstelle von binden, oder Sie könnten die integrierten Funktionen zur Eingabeüberprüfung verwenden, um Ihren Code bei jedem Tastendruck aufzurufen. Mit dieser Lösung erhalten Sie alle Daten, die Sie benötigen - den Wert vor der Änderung, den Wert nach der Änderung, die gedrückte Taste usw.

Eine weitere Möglichkeit besteht darin, die Reihenfolge der Ereignisse zu ändern verarbeitet. Da Ihre Frage speziell gefragt wurde, wie Sie die Reihenfolge ändern können, werde ich darauf eingehen.

Auch wenn eine Bindung mit einem Widget verknüpft ist, wenn Sie etwas wie entry.bind(...) tun, weisen Sie tatsächlich eine Bindung einem "bind tag" (oder "bindtag") zu. Standardmäßig hat jedes Widget einen Bindtag, der mit dem Namen des Widgets übereinstimmt. Andere Bindtags beinhalten die Klasse eines Widgets (zum Beispiel "Entry"), den Pfad des Root-Fensters (zB: ".") Und das spezielle Tag "all". Widgets wird eine Reihe von Bindtags zugewiesen, die in der Reihenfolge verarbeitet werden, in der ein Ereignis empfangen wird. Die Standardreihenfolge wechselt von "am wenigsten" zu "am wenigsten": Widget, Klasse, Toplevel, alle.

Es gibt mehrere Möglichkeiten, die Bindtags zu manipulieren, um das gewünschte Ergebnis zu erzielen. Eine Möglichkeit besteht darin, die Reihenfolge der Bindtags neu anzuordnen. Durch Verschieben des Bindtags, das das Widget darstellt, hinter dem Bindtag, das die Klasse darstellt, behandelt die Klasse das Ereignis, bevor es an das bestimmte Widget übergeben wird.

Eine andere Möglichkeit besteht darin, ein zusätzliches Bindtag nach der Klassenbindung hinzuzufügen und dann Ihre Bindungen in dieses Tag und nicht in das Tag einzufügen, das das Widget darstellt.

Warum eins über das andere wählen? Durch das Umordnen der Reihenfolge werden alle Bindungen auf diesem Widget beeinflusst. Wenn Sie viele Bindungen haben und einige von der Reihenfolge abhängen (so dass beispielsweise bestimmte Tastenanschläge nicht zulässig sind), kann das Ändern der Reihenfolge dazu führen, dass diese Bindungen nicht mehr funktionieren.

Durch die Einführung eines neuen Bindtags können Sie auswählen, welche Bindungen vor Klassenbindungen auftreten und welche danach auftreten.

Im folgenden Code erstelle ich drei Eingabe-Widgets. Der erste verwendet den Standardsatz von Bindtags (im Beispiel explizit festgelegt, obwohl sie mit dem Standard identisch sind). Die zweite ändert die Reihenfolge und die dritte führt ein zusätzliches Bindtag ein. Führen Sie den Code aus und drücken Sie eine Taste, während sich der Fokus in jedem Fenster befindet. Beachten Sie, dass die Bindung im Widget für den ersten Eintrag immer um ein Zeichen zurückbleibt. Dies liegt wiederum daran, dass die Widget-Bindung stattfindet, bevor die Klassenbindung das Zeichen in das Widget einfügt.

Im zweiten und dritten Beispiel erfolgt die Bindung nach der Klassenbindung, so dass die Funktion die Änderung in den Widgets sieht.

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

Ich versuche, eine benutzerdefinierte Bindung zu einem Widget 'Text' zu erstellen und zuzuordnen, aber wenn ich versuche, auf den' Text' zu schreiben, kann ich nicht, nichts passiert. Dies ist der Code: 'self.tab1.text.bindtags (('. Tab1', 'Rahmen', 'n-binding', '.', 'Alle')) self.tab1.text.bind_class ('n -binding ',' ', self.bottom_bar.on_key_pressed' – nbro

+0

@nbro: Es sieht so aus, als hätten Sie den Standard-Bindtag 'Text' entfernt, sodass dem Widget keine Text-Widget-Bindungen zugeordnet sind. –