2011-06-21 163 views
14

如何停止正在处理的事件或切换要调用的函数?删除和更改python中的tkinter事件绑定

修改后的代码:

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

回答

25

您可以只是简单地再次与该事件的新功能调用bind()。既然你没有使用第三个参数add,在bind()这只会覆盖已经存在的任何东西。默认情况下,这个参数是'',但它也接受"+",它将回调已经由该事件触发的回调。

如果您开始使用该可选参数,但您需要使用unbind()函数删除单个回调。当您致电bind()时,返回funcid。您可以将此funcid作为第二个参数传递给unbind()

例子:

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

对于我来说,取消绑定一个回调不工作,但我找到了解决办法。

我可以看到这是一个古老的问题,但对于像我这样的人在面对同样问题时发现这个问题的人来说,这是我做的工作。

您将需要打开源文件Tkinter.py并搜索Misc类的解除绑定方法(如果您使用的是eclipse,很容易知道文件的位置以及通过按下当光标位于代码中的.unbind函数调用时,F3键)。

当你找到它,你会看到这样的事情:

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) 

你需要改变它看起来somethins这样的:

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) 

这应该做的伎俩!

+0

我有porblems unbind呢!你应该得到合并的更改! – timeyyy

+0

@arcra:在Ubuntu 16.10上运行Python 3.5.2,并且仍然存在您修复的相同问题。您的解决方案仍然可以完美工作,因为源还没有打补丁。就像阿登一样,我建议你提出这个建议,以获得信贷,并且确实适用。 –

4

Bryan提供的答案一般效果很好,但是如arcra强调的那样,它可能不会。如果您遇到无法正确解除堆叠回调的问题,请修改官方源代码 - 如果它仍然相同! - 可能是一个解决方案。

下面是我的2分钱给那些仍然发现自己陷入问题的人:请覆盖unbind()方法,请勿直接编辑它。

这样,事实上,您不需要手动更改工作站上的官方源代码(从而打破了软件包管理,或者在下一次软件包更新时重新引入问题,或者在另一个客户端上遇到相同问题, ...):

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) 

然后,而不是实例发生故障的部件(在我的例子中,我使用Canvas)这样

myCanvas = tk.Canvas(...) 

你可以简单的从你的补丁版本实例化它,将需要更新是否且仅当官方源将被更新并固定:

myCanvas = PatchedCanvas(...) 

拆散方法在Misc类,从中BaseWidget继承它当前定义,然后,conseq uenty,小工具,TopLevel,按钮,...

+0

非常感谢!我需要这个! –