Закрытие окна и последующее его открытие в цикле
Хочу написать программу, используя tkinter, которая служит для напоминаний, создал словарь с определенными часами и минутами, по достижению которых появляется диалоговое окно, в котором есть кнопка, после нажатия на которую окно закрывается, но оно должно появиться снова, когда настанет следующее совпадение со временем в словаре, но столкнулся с проблемой зависания окна при нажатии на кнопку. Код:
from datetime import datetime
from tkinter import *
from tkinter import messagebox as mb
import time
def quit():
root.quit()
root = Tk()
root.title("Notification")
Label(text="Alarm", width=30, height=3).pack()
a = Label(text='', width=20, height=3)
a.pack()
Button(text="Ok", width=10, command=quit).pack()
tim = {
"1": [9, 10],
"2": [10, 10],
"3": [11, 10],
"4": [14, 10],
"5": [15, 10],
"6": [16, 20],
"test": [15, 2],
"test2": [15, 3]
}
if root.winfo_screenwidth() > 1920:
w = root.winfo_screenwidth()//4-200
else:
w = root.winfo_screenwidth()//2-150
h = root.winfo_screenheight()//2-100
root.geometry('400x150+{}+{}'.format(w, h))
while True:
current_d = datetime.now()
if current_d.hour == tim["test"][0] and current_d.minute == tim["test"][1] and current_d.second == 0:
a.config(text="Point №1")
root.mainloop()
if current_d.hour == tim["test2"][0] and current_d.minute == tim["test2"][1] and current_d.second == 0:
a.config(text="Point №2")
root.mainloop()
ps Тестировал работу без цикла, и все работало корректно, окно закрывалось и никаких ошибок и зависаний не было
Ответы (1 шт):
В оконном приложении не должно быть никаких вечных циклов в основном потоке - должен быть только вызов функции mainloop(), внутри которой есть свой "вечный" цикл (выполняющийся все время, пока существует главное окно).
Если нужно выполнять какое-то действие периодически (например, сравнивать время с заданным), то планируйте выполнение функции с этим действием с помощью метода root.after(). Пример:
import tkinter as tk
from datetime import datetime, timedelta
root = tk.Tk()
def check_time(start_time, time_delta):
if datetime.now() - start_time >= time_delta:
root.deiconify() # Время истекло - отобразить окно
else:
root.after(500, check_time, start_time, time_delta) # Не истекло - проверить время еще раз через 500 мс
def hide():
root.withdraw() # Скрыть окно
# Запланировать выполнение функции check_time через 500 миллисекунд
root.after(500, check_time, datetime.now(), timedelta(seconds=5))
# Все параметры кроме первых будут переданы в функцию check_time в момент ее вызова
tk.Button(root, text="Скрыть на 5 сек", command=hide).pack()
root.mainloop()