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()