Удаление и изменение привязки события tkinter - PullRequest
16 голосов
/ 22 июня 2011

Как мне остановить обработку события или переключить, какая функция вызывается для него?

Пересмотренный код:

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

Ответы [ 3 ]

31 голосов
/ 22 июня 2011

Вы можете просто просто позвонить 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>")
5 голосов
/ 02 января 2017

Ответ, предоставленный Брайаном, в целом работает хорошо, но, как подчеркнул Аркра, он может и не быть. Если у вас возникла проблема с невозможностью правильно отсоединить сложенный обратный вызов, измените официальный источник - если он все тот же! - может быть решением.

Вот мои 2 цента для тех, кто все еще сталкивается с проблемой: пожалуйста, переопределите метод unbind (), НЕ РЕДАКТИРУЙТЕ ЕГО ПРЯМО.

Таким образом, фактически вам не нужно вручную изменять официальный исходный код на вашей рабочей станции (таким образом, нарушая управление пакетами, или повторно представляя проблему при следующем обновлении пакета, или создавая ту же проблему на другом клиенте). ..):

import tkinter as tk


class PatchedCanvas(tk.Canvas):
    def unbind(self, sequence, funcid=None):
        '''
        See:
            /5522619/udalenie-i-izmenenie-privyazki-sobytiya-tkinter
            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(...)

В настоящее время метод unbind определен в классе Misc, из которого его наследует BaseWidget, а затем, соответственно, Widget, TopLevel, Button, ...

5 голосов
/ 29 мая 2014

Для меня открепление одного обратного вызова не работало, но я нашел решение.

Я вижу, что это старый вопрос, но для тех, кто, как и я, находит этот вопрос, сталкиваясь с той же проблемой, это то, что я сделал, чтобы он работал.

Вам нужно будет открыть исходный файл Tkinter.py и найти метод unbind класса Misc (если вы используете eclipse, легко узнать местоположение файла и строку, в которой эта функция определяется нажатием клавиши F3). клавиша, когда курсор находится над вызовом функции .unbind в вашем коде).

Когда вы найдете это, вы должны увидеть что-то вроде этого:

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)

Вам нужно изменить его, чтобы он выглядел примерно так:

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)

Это должно сработать!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...