Как заставить работать прослушиватель событий Tkinter? - PullRequest
1 голос
/ 16 октября 2019

Я использую Tkinter для графического интерфейса небольшого инструмента, написанного на Python. По сути, я просто хочу, чтобы callback-метод выполнялся, как только содержимое виджета записи изменилось. Это можно сделать с помощью собственных переменных классов Tkinter (StringVar, BooleanVar и т. Д. - подробности см. В документации: http://effbot.org/tkinterbook/variable.htm).

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

  • Я создал экземпляр Tk непосредственно в конструкторе моегоКласс GUI - такое же поведение.
  • Я унаследовал непосредственно от класса Tk (вместо Frame) - такое же поведение.
  • Я разместил обратный вызов за пределами класса - такое же поведение.
Единственная идея, которая у меня есть, заключается в том, что проблема может быть связана с областью действия, которую я пытался проверить.

Фрагмент рабочего кода:

from tkinter import *
import tkinter as tk

def text_changed(*args):
    print("Text changed.")

top = tk.Tk()

string_listener = StringVar()
string_listener.set("Init Text")
string_listener.trace("w", text_changed)

entry_widget = tk.Entry(top, textvariable = string_listener)
entry_widget.pack()

top.mainloop()

Не работаетфрагмент кода

from tkinter import *
import tkinter as tk

root = tk.Tk()

class GUI(tk.Frame):
    def __init__(self, master=root):
        super(GUI, self).__init__(master)

        string_listener = StringVar()
        string_listener.set("Init Text")
        string_listener.trace("w", self.text_changed_callback)

        entry_widget = tk.Entry(master, textvariable=string_listener)
        entry_widget.pack()

    def text_changed_callback(self, *args):
        print("Text changed.")

gui = GUI()
gui.mainloop()

Как и в рабочем примере, мой код должен печатать Text changed. каждый раз, когда символ удаляется или добавляется к строке в extry-виджете.

1 Ответ

1 голос
/ 16 октября 2019

Проблема в том, что string_listener является локальной переменной, и python уничтожает переменную, когда __init__ завершает работу. В исходном коде этого не происходит, поскольку переменная создается в глобальной области видимости.

Простое решение - сохранить ссылку в качестве атрибута класса:

import tkinter as tk

root = tk.Tk()

class GUI(tk.Frame):
    def __init__(self, master=root):
        super(GUI, self).__init__(master)

        self.string_listener = tk.StringVar()
        self.string_listener.set("Init Text")
        self.string_listener.trace("w", self.text_changed_callback)

        entry_widget = tk.Entry(master, textvariable=self.string_listener)
        entry_widget.pack()

    def text_changed_callback(self, *args):
        print("Text changed.")

gui = GUI()
gui.mainloop()

note: Я также изменил StringVar на tk.StringVar, чтобы можно было удалить избыточный импорт подстановочных знаков из tkinter.

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