131 lines
3.8 KiB
Python
131 lines
3.8 KiB
Python
import threading
|
|
import queue
|
|
import time
|
|
|
|
class ThreadManager:
|
|
"""Manager for thread operations."""
|
|
|
|
def __init__(self, root, on_done=None, on_error=None, on_message=None):
|
|
"""
|
|
Initialize the thread manager.
|
|
|
|
Args:
|
|
root: The Tkinter root window.
|
|
on_done: Callback function for when a thread completes.
|
|
on_error: Callback function for when a thread encounters an error.
|
|
on_message: Callback function for thread messages.
|
|
"""
|
|
self.root = root
|
|
self.queue = queue.Queue()
|
|
self.on_done = on_done
|
|
self.on_error = on_error
|
|
self.on_message = on_message
|
|
self._setup_queue_check()
|
|
|
|
def _setup_queue_check(self):
|
|
"""Set up the queue check for thread status updates."""
|
|
self._check_queue()
|
|
|
|
def _check_queue(self):
|
|
"""Check the queue for thread status updates."""
|
|
try:
|
|
while True:
|
|
message = self.queue.get_nowait()
|
|
if message == "DONE":
|
|
if self.on_done:
|
|
self.on_done()
|
|
elif message == "ERROR":
|
|
if self.on_error:
|
|
self.on_error("An error occurred during processing.")
|
|
else:
|
|
if self.on_message:
|
|
self.on_message(message)
|
|
except queue.Empty:
|
|
pass
|
|
finally:
|
|
self.root.after(100, self._check_queue)
|
|
|
|
def start_thread(self, target, args=(), kwargs=None):
|
|
"""Start a new thread.
|
|
|
|
Args:
|
|
target: The target function to run in the thread.
|
|
args: Arguments to pass to the target function.
|
|
kwargs: Keyword arguments to pass to the target function.
|
|
|
|
Returns:
|
|
threading.Thread: The started thread.
|
|
"""
|
|
if kwargs is None:
|
|
kwargs = {}
|
|
|
|
thread = threading.Thread(
|
|
target=self._thread_wrapper,
|
|
args=(target, args, kwargs),
|
|
daemon=True
|
|
)
|
|
thread.start()
|
|
return thread
|
|
|
|
def _thread_wrapper(self, target, args, kwargs):
|
|
"""Wrapper for thread execution to handle errors and messages."""
|
|
try:
|
|
result = target(*args, **kwargs)
|
|
self.queue.put("DONE")
|
|
return result
|
|
except Exception as e:
|
|
self.queue.put("ERROR")
|
|
if self.on_error:
|
|
self.on_error(str(e))
|
|
raise
|
|
|
|
def put_message(self, message):
|
|
"""Put a message in the queue.
|
|
|
|
Args:
|
|
message: The message to put in the queue.
|
|
"""
|
|
self.queue.put(message)
|
|
|
|
# Example usage (for testing)
|
|
if __name__ == '__main__':
|
|
import tkinter as tk
|
|
from tkinter import ttk, messagebox
|
|
|
|
root = tk.Tk()
|
|
root.title("Thread Manager Test")
|
|
root.geometry("400x300")
|
|
|
|
def on_done():
|
|
print("Thread completed successfully")
|
|
messagebox.showinfo("Success", "Thread completed successfully")
|
|
|
|
def on_error(error):
|
|
print(f"Thread error: {error}")
|
|
messagebox.showerror("Error", str(error))
|
|
|
|
def on_message(message):
|
|
print(f"Thread message: {message}")
|
|
|
|
# Create thread manager
|
|
thread_manager = ThreadManager(
|
|
root,
|
|
on_done=on_done,
|
|
on_error=on_error,
|
|
on_message=on_message
|
|
)
|
|
|
|
# Test function
|
|
def test_function():
|
|
for i in range(5):
|
|
thread_manager.put_message(f"Processing step {i+1}")
|
|
time.sleep(1)
|
|
return "Test result"
|
|
|
|
# Test button
|
|
def start_test():
|
|
thread_manager.start_thread(test_function)
|
|
|
|
ttk.Button(root, text="Start Test", command=start_test).pack(pady=5)
|
|
|
|
root.mainloop() |