2011-06-21 11 views
14

Jak zatrzymać przetwarzanie zdarzenia lub zmienić funkcję, która jest do niego przypisana?Usuwanie i zmiana powiązania zdarzenia tkinter w pythonie

Aktualizowano Kod:

from Tkinter import * 

class GUI: 
    def __init__(self,root): 
     Window = Frame(root) 
     self.DrawArea = Canvas(Window) 
     self.DrawArea.pack() 
     Window.pack() 

     self.DrawArea.bind("<Button 1>",self.starttracking) 

    def updatetracking(self,event): 
     print event.x,event.y 

    def finishtracking(self,event): 
     self.DrawArea.bind("<Button 1>",self.starttracking) 
     self.DrawArea.unbind("<Motion>") 

    def starttracking(self,event): 
     print event.x,event.y 
     self.DrawArea.bind("<Motion>",self.updatetracking) 
     self.DrawArea.bind("<Button 1>",self.finishtracking) 



if __name__ == '__main__': 
    root = Tk() 
    App = GUI(root) 
    root.mainloop() 

Odpowiedz

25

Można po prostu wystarczy zadzwonić bind() dzięki nowej funkcji dla zdarzenia. Ponieważ nie używasz trzeciego parametru, add, w bind() spowoduje to tylko nadpisanie tego, co już tam jest. Domyślnie ten parametr to '', ale akceptuje także "+", który dodaje wywołanie zwrotne do wywołań zwrotnych już wywołanych przez to zdarzenie.

Jeśli zaczniesz używać tego opcjonalnego argumentu, musisz jednak użyć funkcji unbind(), aby usunąć poszczególne wywołania zwrotne. Po wywołaniu bind() zwracana jest nazwa funcid. Możesz przekazać ten funcid jako drugi parametr do unbind().

Przykład:

self.btn_funcid = self.DrawArea.bind("<Button 1>", self.my_button_callback, "+") 

# Then some time later, to remove just the 'my_button_callback': 
self.DrawArea.unbind("<Button 1>", self.btn_funcid) 

# But if you want to remove all of the callbacks for the event: 
self.DrawArea.unbind("<Button 1>") 
4

Dla mnie Rozpinanie pojedynczy callback nie działa, ale znalazłem rozwiązanie.

Widzę, że jest to stare pytanie, ale dla tych, którzy, podobnie jak ja, znajdują to pytanie w obliczu tego samego problemu, właśnie to zrobiłem, aby działało.

Będziesz musiał otworzyć plik źródłowy Tkinter.py i wyszukać metodę wiązania według klasy Misc (jeśli używasz Eclipse, łatwo jest poznać położenie pliku i linię, w której ta funkcja jest zdefiniowana przez naciśnięcie klawisza Klawisz F3, gdy kursor znajduje się nad wywołaniem funkcji .unbind w kodzie).

Kiedy go znaleźć, powinieneś zobaczyć coś takiego:

def unbind(self, sequence, funcid=None): 
     """Unbind for this widget for event SEQUENCE the 
     function identified with FUNCID.""" 
     self.tk.call('bind', self._w, sequence, '') 
     if funcid: 
      self.deletecommand(funcid) 

Musisz zmienić go szukać somethins tak:

def unbind(self, sequence, funcid=None): 
     """Unbind for this widget for event SEQUENCE the 
     function identified with FUNCID.""" 
    if not funcid: 
     self.tk.call('bind', self._w, sequence, '') 
     return 
    func_callbacks = self.tk.call('bind', self._w, sequence, None).split('\n') 
    new_callbacks = [l for l in func_callbacks if l[6:6 + len(funcid)] != funcid] 
    self.tk.call('bind', self._w, sequence, '\n'.join(new_callbacks)) 
    self.deletecommand(funcid) 

To powinno załatwić sprawę!

+0

miałem też porblemy z odpinaniem! Powinieneś połączyć zmiany! – timeyyy

+0

@arcra: Uruchamianie Pythona 3.5.2 na Ubuntu 16.10 i wciąż ten sam problem, który rozwiązałeś. Twoje rozwiązanie nadal działa idealnie, ponieważ źródło wciąż nie zostało jeszcze załatane. Podobnie jak w przypadku Arden, sugeruję, abyś go zaproponował, aby uzyskać kredyt i zdecydowanie go zastosować. –

4

Odpowiedź dostarczona przez Bryana ogólnie działa dobrze, ale jak podkreślił arcra, może nie być. Jeśli wystąpi problem polegający na tym, że nie można poprawnie usunąć powiązanego wywołania zwrotnego, modyfikując oficjalne źródło - jeśli nadal jest taki sam! - może być rozwiązaniem.

Oto moje 2 centy dla tych, którzy wciąż mają problem z tym problemem: proszę zastąpić metodę unbind(), NIE EDYTUJ GO BEZPOŚREDNIO.

W ten sposób nie trzeba ręcznie zmieniać oficjalnego kodu źródłowego na stacji roboczej (w ten sposób łamiąc zarządzanie pakietami lub ponownie wprowadzając problem przy następnej aktualizacji pakietu lub mając ten sam problem na innym kliencie, ...):

import tkinter as tk 


class PatchedCanvas(tk.Canvas): 
    def unbind(self, sequence, funcid=None): 
     ''' 
     See: 
      http://stackoverflow.com/questions/6433369/ 
      deleting-and-changing-a-tkinter-event-binding-in-python 
     ''' 

     if not funcid: 
      self.tk.call('bind', self._w, sequence, '') 
      return 
     func_callbacks = self.tk.call(
      'bind', self._w, sequence, None).split('\n') 
     new_callbacks = [ 
      l for l in func_callbacks if l[6:6 + len(funcid)] != funcid] 
     self.tk.call('bind', self._w, sequence, '\n'.join(new_callbacks)) 
     self.deletecommand(funcid) 

Następnie zamiast instancji widget niepowodzeniem (w moim przykładzie używam płótnie) jak to

myCanvas = tk.Canvas(...) 

będzie po prostu oznacz ją z wersją połatany, które potrzebują aktualizacji, jeśli i tylko wtedy, gdy oficjalnym źródłem będzie aktualizowany i stałe:

myCanvas = PatchedCanvas(...) 

Sposób unbind jest aktualnie zdefiniowane w klasie Misc, z którego BaseWidget dziedziczy go, a następnie Conseq uenty, Widget, TopLevel, Button, ...

+0

Wielkie dzięki! Potrzebowałem tego! –

Powiązane problemy