ниже скрипта, который использует угрозу и меняет тип курсора при запуске потока и после его завершения.Он имитирует обратный отсчет с интервалом в 1 секунду.
Я установил родительский курсор, но если вы сохраняете ссылку на другой виджет, например кнопку, вы можете выполнить ту же работу.
Вызов класса MyThread принудительно устанавливает тип курсора как
self.parent.config (cursor = "watch")
и, когда поток заканчивается, self.check= Ложь, мы сбрасываем тип курсора
self.parent.config (cursor = "")
#!/usr/bin/python3
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import threading
import queue
import time
class MyThread(threading.Thread):
def __init__(self,parent, queue, count):
threading.Thread.__init__(self)
self.parent = parent
self.parent.config(cursor="watch")
self.queue = queue
self.check = True
self.count = count
def stop(self):
self.check = False
def run(self):
while self.check:
if self.count <1:
self.parent.config(cursor="")
self.check = False
else:
self.count -= 1
time.sleep(1)
self.queue.put(self.count)
class Main(ttk.Frame):
def __init__(self, parent):
super().__init__()
self.parent = parent
self.parent.config(cursor="")
self.queue = queue.Queue()
self.my_thread = None
self.spins = tk.IntVar()
self.count = tk.IntVar()
self.spins.set(5)
self.init_ui()
def init_ui(self):
f = ttk.Frame()
ttk.Label(f, text = "Set count").pack()
tk.Spinbox(f, from_=2, to=20, textvariable= self.spins).pack()
ttk.Label(f, text = "Get count").pack()
ttk.Label(f, textvariable = self.count).pack()
w = ttk.Frame()
self.start = ttk.Button(w, text="Start", command=self.start_count).pack()
ttk.Button(w, text="Stop", command=self.stop_count).pack()
ttk.Button(w, text="Close", command=self.on_close).pack()
f.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
w.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)
def start_count(self):
if (threading.active_count()!=0):
self.my_thread = MyThread(self.parent, self.queue,self.spins.get())
self.my_thread.start()
self.on_periodic_call()
def stop_count(self):
if self.my_thread is not None:
if(threading.active_count()!=1):
self.my_thread.stop()
def on_periodic_call(self):
self.on_check_queue()
if self.my_thread.is_alive():
self.after(1, self.on_periodic_call)
else:
pass
def on_check_queue(self):
while self.queue.qsize():
try:
self.count.set(self.queue.get(0))
except queue.Empty:
pass
def on_close(self):
if self.my_thread is not None:
if(threading.active_count()!=1):
self.my_thread.stop()
self.parent.on_exit()
class App(tk.Tk):
"""Start here"""
def __init__(self):
super().__init__()
self.protocol("WM_DELETE_WINDOW", self.on_exit)
self.set_style()
self.set_title()
Main(self)
def set_style(self):
self.style = ttk.Style()
#('winnative', 'clam', 'alt', 'default', 'classic', 'vista', 'xpnative')
self.style.theme_use("clam")
def set_title(self):
s = "{0}".format('Simple App')
self.title(s)
def on_exit(self):
"""Close all"""
if messagebox.askokcancel("Simple App", "Do you want to quit?", parent=self):
self.destroy()
if __name__ == '__main__':
app = App()
app.mainloop()