#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")