В Tkinter привязать действие к виджету
Реализую игру "Магический шар", используя библиотеку Tkinter в стандартном пакете Python. Написал код окна и виджетов в нем:
- область для написания вопросов (на основе tk.Text) + кнопка "Спросить"
- область для вывода ответов (также tk.Text)
- область tk.Text для написания новых вариантов ответов (здесь мы как бы "обучаем" шар).
Функционал простой и, конечно, следом потребует доработки (выход из игры, обновление области вопросы и ответов, простой анализ на основе регулярных выражений - скажем, чтобы игра видела знак вопроса в конце вопросительного предложения). Функции (обработчики событий):
- список ответов
- приглашение задать вопрос и его "обдумывание" + случайный ответ (пока так, но следом случайный ответ перенесу в отдельную функцию для области ответов)
- далее напишу функцию обработки новых вопросов.
Работаю в среде Jupyter Notebook. Испытал проблемы:
- если ставлю обработку ввода текста
print(event.char), то вывод полученного от пользователя текста осуществляется в консоль Jupyter, а не в окно программы. Как сделать обратное? Причем если пишу функцию просто для вывода текста с одной приведенной строкой, то вывод идет туда и туда, но тогда дальнейшая логика в обработчике отсутствует. - заданный функцией диалог с пользователем ("Задайте свой вопрос: ") также отправляется в консоль.
Таким образом, питон tkinter видит события в виджете текста, но после их обработки результат дает в консоль.
Код:
# Функция задает вопрос пользователю, а затем возвращает случайные результаты из ответов
def answerQuery(event):
# print(event.char)
question = input("Прошу Вас - задайте свой вопрос: ")
print("Я заглядываю за повороты судьбы, чтобы узнать о грядущем")
time.sleep(2)
print("Хмм...")
time.sleep(2)
print(random.choice(responses)) # responses - список ответов
# Связывает событие нажатия клавиши с answerQuery()
# text_box_question - область tk.Text для написания вопросов
text_box_question.bind('<Key>', answerQuery)
Ответы (1 шт):
Читайте текст из вашего виджета:
question = text_box_question.get("1.0", END)
И выводите в другой:
text_box_answer.insert(END, "Хмм..." + "\n")
wnd.update_idletasks()
time.sleep(2)
text_box_answer.insert(END, random.choice(responses) + "\n")
Но лучше sleep() не использовать. Этим вы заблочите весь UI (будет казаться, что программа 'зависла'). Вместо этого можно использовать метод after() (отложенное исполнение кода). Например так:
wnd.after(2000, lambda: text_box_answer.insert(END, random.choice(responses) + "\n"))