Кнопка Tkinter по-прежнему реагирует на нажатие после отключения и обновления

#python #user-interface #tkinter

#python #пользовательский интерфейс #tkinter

Вопрос:

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

Когда я нажимаю кнопку, она, похоже, отключена, и команда выполняется. Но когда я нажимаю кнопку, когда она отключена, команда выполняется во второй раз после завершения первого выполнения.

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

 import tkinter as tk
import time


class Button:
    def __init__(self, master):
        frame=tk.Frame(master)
        frame.pack()
        self.button1=tk.Button(frame, text="Ready",bg="green", fg="white", command=self.click)
        self.button1.pack()

    def click(self):
        self.button1.config(bg="red", text="Busy", state="disabled")
        self.button1.update()
        doSth()
        self.button1.config(bg="green", fg="white", text="Ready", state="normal")
        self.button1.update()


def doSth():
    time.sleep(3)
    print("done")


root = tk.Tk()
b = Button(root)
root.mainloop()
  

Комментарии:

1. Очень странно. effbot.org/tkinterbook/widget.htm#Tkinter . Widget.update-метод предлагает не использовать update внутри обратного вызова, но переключение на update_idletasks только усугубляет проблему — вместо разрешения двух кликов он разрешает неограниченное количество кликов.

2. tkinter запускает все в одном потоке. Когда вы запускаете длительные процессы, подобные sleep , она останавливается mainloop и не может корректно обновлять виджеты. Иногда это выглядит как замораживание окна (зависает). Вы должны запустить длительный процесс в новом потоке

3. Вам следует изменить имя вашего класса «Button», потому что у tkinter уже есть класс Button. Это не решит вашу проблему, но это должно быть сделано. Я знаю, что вы импортировали tkinter как tk, но все же.

Ответ №1:

Когда вы нажимаете кнопку во время sleep , вы ставите в очередь нажатие кнопки для обработки в следующем цикле обновления. Во время sleep tkinter не обновляется. После sleep вы возвращаете кнопку в нормальное состояние, прежде чем функция вернется и щелчок будет обработан. Поскольку кнопка снова активна, click вызывается снова.

Вы можете противостоять этому, разрешив tkinter обновить, прежде чем снова активировать кнопку, это избавит от любых событий нажатия в очереди, пока кнопка все еще деактивирована.

 def click(self):
    self.button1.config(bg="red", text="Busy", state="disabled")
    self.button1.update()
    doSth()
    self.button1.update()
    self.button1.config(bg="green", fg="white", text="Ready", state="normal")