2010-08-17 10 views
10

Chcę powiązać zdarzenia własne po połączeniach klas widgetu Text, aby zmienić tekst widgetu po wywołaniu funkcji wiązania. Moje powiązanie, na przykład self.text.bind("<Key>", self.callback), jest wywoływane przed zmianą zawartości widżetu Tekst.Jak powiązać zdarzenia własne w widgecie Tekst Tkinter po powiązaniu go z widżetem Tekst?

+0

Jaką "normalną oprawę" używasz? Proszę pokazać kod –

+0

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

+0

, więc na początku nazywa się self.callback, a następnie ten klucz będzie wpisany w widgecie tekstowym – vladimar

Odpowiedz

20

To, co dzieje się w twoim przypadku, polega na tym, że twoje powiązanie do drukowania wartości ma miejsce przed związaniem klasy, a to powiązanie klasy faktycznie bierze użytkownika i umieszcza go w widgecie. Istnieje kilka sposobów rozwiązania tego problemu. Możesz połączyć się z <KeyRelease> zamiast <KeyPress> lub możesz użyć wbudowanych funkcji sprawdzania poprawności wpisu, aby Twój kod był wywoływany przy każdym naciśnięciu klawisza. Dzięki temu rozwiązaniu otrzymasz wszystkie potrzebne dane - wartość przed zmianą, wartość po zmianie, naciśnięty klawisz itp.

Kolejnym wyborem jest zmiana kolejności zdarzeń obrobiony. Ponieważ twoje pytanie dotyczyło konkretnie sposobu zmiany zamówienia, to właśnie się do niego odezwę.

Nawet jeśli powiązanie wydaje się być powiązane z widżetem, gdy robisz coś takiego jak entry.bind(...), faktycznie przypisujesz powiązanie do "tagu bind" (lub "bindtag"). Domyślnie każdy widget ma bindtag, który jest taki sam jak nazwa widgetu. Inne bindtagi obejmują klasę widgetu (na przykład "Entry"), ścieżkę okna głównego (np .: ".") I specjalny znacznik "all". Widgety mają przypisany zestaw bindtagów, które są przetwarzane w kolejności po odebraniu zdarzenia. Domyślna kolejność przechodzi od najbardziej do najmniej szczegółowego: widget, klasa, toplevel, all.

Istnieje kilka sposobów manipulowania bindtagami, aby uzyskać pożądany efekt. Jednym z nich jest zmiana kolejności bindtagów. Przesuwając bindtag, który reprezentuje widżet po sygnaturze bindtag reprezentującej klasę, klasa zajmie się zdarzeniem przed przekazaniem go do określonego widgetu.

Kolejnym wyborem jest dodanie dodatkowego bindtag po powiązaniu klasy, a następnie umieszczenie powiązań na tym znaczniku zamiast na znaczniku reprezentującym widget.

Dlaczego warto wybrać jeden nad drugim? Przestawiając porządek, wpłyniesz na wszystkie powiązania tego widżetu. Jeśli masz wiele powiązań, a niektóre zależą od kolejności (aby np. Uniemożliwić niektóre klawisze), zmiana kolejności może spowodować, że te powiązania przestaną działać.

Wprowadzając nowy bindtag, można wybrać, które wiązania mają miejsce przed wiązaniami klas, a które później.

W poniższym kodzie utworzę trzy widżety wpisu. Pierwsza używa domyślnego zestawu bindtags (jawnie ustawionego w przykładzie, chociaż są one identyczne z domyślnymi). Drugi zmienia kolejność, a trzeci wprowadza dodatkowy bindtag. Uruchom kod, a następnie naciśnij klawisz, gdy fokus znajduje się w każdym oknie. Zauważ, że w pierwszym widżecie wpisu powiązanie zawsze wydaje się być jedną postacią. Ponownie, dzieje się tak, ponieważ powiązanie widgetu następuje przed powiązaniem klasy, umieszczając znak w widgecie.

W drugim i trzecim przykładzie powiązanie następuje po powiązaniu klasy, dzięki czemu funkcja widzi zmianę w widżetach.

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

Próbuję utworzyć i powiązać niestandardowe powiązanie z widżetem 'Text', ale gdy próbuję pisać na' Text', nie mogę, nic się nie dzieje. To jest kod: '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: wygląda na to, że usunąłeś domyślny bindtag' Text', więc żadne powiązania widgetu tekstowego nie są powiązane z widżetem. –

Powiązane problemy