В Tkinter как заставить кнопку менять цвет при нажатии?
Вроде бы, для этого требуется всего лишь указать параметр activebackground, однако при его добавлении кнопка хотя и функционально работает, но статична.
Второй вопрос. Я пишу программу магического шара, которая при заданном ей вопросе отдает случайный ответ из имеющегося в ее списке. Сейчас функция ответа шара привязана к кнопке "Спросить". И так выходит, что обработчик события реагирует даже на пустое поле без заданного в нем вопроса. Как указать программе не отвечать (или отвечать чем-то вроде "Задайте вопрос"), если поле с вопросом пусто?
# кнопка для ввода вопроса в программу
button_ask = tk.Button(
master=frame_question_answer,
text='Спросить',
width=15,
height=2,
bg='#B533FF',
fg='yellow',
activebackground='red' # почему-то цвет при нажатии на красный не меняется
)
button_ask.grid(
row=3, column=0, sticky='e'
)
# Обработчик вопроса пользователя
def questionQuery():
question = text_box_question.get('1.0', tk.END) # читаем текст из виджета text_box_question
time.sleep(2)
# Функция возврата случайных ответов
def answerQuery():
text_box_answer.insert(tk.END, 'Хмм...' + '\n') # и выводим в виджет text_box_answer
window.update_idletasks()
time.sleep(2)
text_box_answer.insert(tk.END, 'Я заглядываю за повороты судьбы, чтобы узнать о грядущем' + '\n')
window.update_idletasks()
window.after(2000, lambda: text_box_answer.insert(tk.END, random.choice(responses) + '\n'))
def call_funcs(event):
questionQuery()
answerQuery()
# привязываем к кнопке обработку события
button_ask.bind('<Button>', call_funcs)
Ответы (2 шт):
Вам портит "всю малину" функция sleep(), которая на время ожидания блокирует любую перерисовку. А так как из-за button_ask.bind('<Button>', call_funcs) функция позовётся при нажатии кнопки мыши, а не при отпускании, как по идее правильнее будет - у кнопки почти не остаётся шанса поменять свой цвет.
Альтернативы, как я вижу, такие:
- Вешать обработчик нажатия напрямую на кнопку, а не через
bind().
import tkinter as tk
import time
def questionQuery():
root.update_idletasks()
time.sleep(2)
btn.configure(text='Done')
root = tk.Tk()
btn = tk.Button(root, activebackground='red', text="Press me", command=questionQuery)
btn.pack()
root.mainloop()
- Или использовать отложенное исполнение части функции при помощи метода
after()и никогда не использоватьsleep()в UI.
import tkinter as tk
import time
def questionQuery_After():
btn.configure(text='Done')
def questionQuery(event):
root.update_idletasks()
root.after(2000, questionQuery_After)
root = tk.Tk()
btn = tk.Button(root, activebackground='red', text="Press me")
btn.pack()
btn.bind('<Button>', questionQuery)
root.mainloop()
Побуду немного археологом, но столкнулся с такой же проблемой. Удаление слипов так же не помогло. Помогло наоборот реакцию на нажатие сделать не через command=...., а через bind. И заработало как надо, даже со sleep