2011-06-21 99 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という3番目のパラメータを使用していないので、bind()には既に存在するものが上書きされます。デフォルトではこのパラメータは''ですが、"+"も受け入れます。これにより、そのイベントによって既にトリガされたコールバックにコールバックが追加されます。

ただし、オプションの引数を使用する場合は、unbind()関数を使用して個々のコールバックを削除する必要があります。 bind()に電話するとfuncidが返されます。このfuncidを第2のパラメータとして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.""" 
    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) 

:あなたはこのようなsomethinsを見て、それを変更する必要が

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) 

を!

+0

私はアンバインドでポルブレを持っていました!あなたは変更をマージする必要があります! – 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) 

その後、代わりにこの

myCanvas = tk.Canvas(...) 

のようなあなたの失敗ウィジェットを(私の例では、私はキャンバスを使用)インスタンス化するのは、単に場合は、更新が必要になりますあなたのパッチを当てたバージョンからそれをインスタンス化します公式ソースが更新され、固定される場合にのみ:

myCanvas = PatchedCanvas(...) 

バインド解除方法は、現在その他のクラスで定義されている、BaseWidgetはそれを継承し、その後、conseqそこからウィジェット、TopLevel、ボタン、...

+0

ありがとう!私はこれが必要でした! –

関連する問題