svg-processor/gui/thread_manager.py
2025-05-16 18:15:31 +04:00

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