2011-06-21 24 views
14

Làm cách nào để ngăn sự kiện được xử lý hoặc chuyển đổi chức năng nào được gọi cho nó?Xóa và thay đổi ràng buộc sự kiện tkinter trong python

Mã sửa đổi:

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() 

Trả lời

25

Bạn có thể chỉ đơn giản là chỉ cần gọi bind() một lần nữa với các chức năng mới cho sự kiện này. Vì bạn không sử dụng tham số thứ ba, add, trong bind(), điều này sẽ chỉ ghi đè bất kỳ thông tin nào đã có. Theo mặc định, tham số này là '' nhưng nó cũng chấp nhận "+", sẽ thêm một cuộc gọi lại vào các cuộc gọi lại đã được kích hoạt bởi sự kiện đó.

Nếu bạn bắt đầu sử dụng đối số tùy chọn đó, bạn sẽ cần sử dụng chức năng unbind() để xóa từng cuộc gọi lại. Khi bạn gọi tới số bind(), số funcid sẽ được trả lại. Bạn có thể chuyển số funcid này làm tham số thứ hai cho unbind().

Ví dụ:

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

Đối với tôi, unbinding một callback đơn đã không làm việc, nhưng tôi tìm thấy một giải pháp.

Tôi có thể thấy đây là một câu hỏi cũ, nhưng đối với những người, giống như tôi, tìm câu hỏi này khi đối mặt với cùng một vấn đề, đây là những gì tôi đã làm để làm cho nó hoạt động.

Bạn sẽ cần phải mở tệp nguồn Tkinter.py và tìm phương thức không xác định của lớp Misc (nếu bạn đang sử dụng nhật thực thật dễ dàng để biết vị trí của tệp và dòng trong đó hàm này được xác định bằng cách nhấn Phím F3 khi con trỏ kết thúc cuộc gọi hàm .unbind trong mã của bạn).

Khi bạn tìm thấy nó, bạn sẽ thấy một cái gì đó như thế này:

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) 

Bạn cần phải thay đổi nó để tìm somethins như thế này:

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) 

Điều đó sẽ làm các trick!

+0

tôi đã có các biểu tượng với unbind quá! Bạn sẽ nhận được các thay đổi đã hợp nhất! – timeyyy

+0

@arcra: Chạy Python 3.5.2 trên Ubuntu 16.10 và vẫn gặp sự cố tương tự mà bạn đã khắc phục. Giải pháp của bạn vẫn hoạt động hoàn hảo vì nguồn vẫn chưa được vá. Giống như Arden, tôi đề nghị bạn đề xuất nó để có được tín dụng và áp dụng nó một cách chắc chắn. –

4

Câu trả lời được cung cấp bởi Bryan thường hoạt động tốt, nhưng như arcra đã nhấn mạnh, nó có thể không. Nếu bạn gặp sự cố không thể hủy chính xác một cuộc gọi lại được xếp chồng lên nhau, hãy sửa đổi nguồn chính thức - nếu nó vẫn giống nhau! - có thể là một giải pháp.

Ở đây theo 2 xu của tôi cho những người vẫn thấy mình bị mắc kẹt với vấn đề: xin vui lòng, ghi đè phương pháp unbind(), KHÔNG CHỈNH SỬA CNTT TRỰC TIẾP. Bằng cách này, trên thực tế, bạn không cần phải tự thay đổi mã nguồn chính thức trên máy trạm của bạn (do đó phá vỡ quản lý gói, hoặc giới thiệu lại vấn đề trong bản cập nhật gói tiếp theo hoặc gặp vấn đề tương tự trên một ứng dụng khách khác, ...):

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) 

Sau đó, thay vì instantiating phụ tùng không bạn (trong ví dụ của tôi, tôi sử dụng Canvas) như thế này

myCanvas = tk.Canvas(...) 

bạn sẽ chỉ đơn giản là nhanh chóng nó từ phiên bản vá của bạn sẽ cần một bản cập nhật nếu và chỉ khi các nguồn chính thức sẽ được cập nhật và cố định:

myCanvas = PatchedCanvas(...) 

phương pháp unbind hiện đang được định nghĩa trong lớp misc, từ đó BaseWidget thừa hưởng nó và sau đó, conseq uenty, Widget, TopLevel, Button, ...

+0

Cảm ơn rất nhiều! Tôi cần điều này! –

Các vấn đề liên quan