Jan-05-2025, 07:13 PM
(This post was last modified: Jan-05-2025, 08:24 PM by deanhystad.)
Hi everyone,
I’m working on a project that involves creating a GUI region selector in Tkinter. The goal is to allow the user to draw a rectangle to select a screen region, display a red outline of the selected area, and have the main program continue running after the selection is made.
What My Code Does:
select_area(coord_queue) (from area_selector.py):
Opens a semi-transparent overlay window that allows the user to select a region by clicking and dragging.
After the selection is completed, the coordinates are passed to a queue.Queue().
create_outline_window(root, coords) (from area_selector.py):
Creates a borderless window at the selected coordinates.
Draws a red rectangle outline with a transparent center.
Adds a "Close" button to close the outline window.
Main Program Flow (operate.py):
Uses start_selection(coord_queue) to run select_area() in a separate thread.
Waits for the coordinates and then opens the red outline window.
Problem
When I call create_outline_window():
The program stalls after the selection window is closed, and the red outline is not persistant and must be exited to allow the program flow to keep going
I believe the issue lies in how I’m handling threads and the mainloop() calls. I may be mixing too many Tkinter event loops (root.mainloop() vs Toplevel()), causing the GUI to become unresponsive.
Main Code Block in operate.py:
Multiple Tkinter root windows?
I’m creating multiple Tk() and Toplevel() windows. Could these interfere with each other?
Mainloop Conflict:
I’m calling mainloop() in different threads and potentially mixing GUI contexts. Maybe I need a more synchronized approach?
Improper Thread Handling:
The selection overlay and outline window both use threading.Thread(). Perhaps I’m not handling thread termination properly?
The expected behavior is that it would keep the red outline there and move onto the next lines of code since it's multi-threaded. But it does not do that. Does anyone know how to resolve this?
Here's a video
The program stalls after the selection is made. The red outline is not persistent and must be exited to allow the program flow to keep going. I thought threading it would eliminate this flow issue and allow it to keep going, but it does not.
Here are the main files:
operate.py (Size: 6.06 KB / Downloads: 50)
area_selector.py (Size: 4.42 KB / Downloads: 48)
I’m working on a project that involves creating a GUI region selector in Tkinter. The goal is to allow the user to draw a rectangle to select a screen region, display a red outline of the selected area, and have the main program continue running after the selection is made.
What My Code Does:
select_area(coord_queue) (from area_selector.py):
Opens a semi-transparent overlay window that allows the user to select a region by clicking and dragging.
After the selection is completed, the coordinates are passed to a queue.Queue().
create_outline_window(root, coords) (from area_selector.py):
Creates a borderless window at the selected coordinates.
Draws a red rectangle outline with a transparent center.
Adds a "Close" button to close the outline window.
Main Program Flow (operate.py):
Uses start_selection(coord_queue) to run select_area() in a separate thread.
Waits for the coordinates and then opens the red outline window.
Problem
When I call create_outline_window():
The program stalls after the selection window is closed, and the red outline is not persistant and must be exited to allow the program flow to keep going
I believe the issue lies in how I’m handling threads and the mainloop() calls. I may be mixing too many Tkinter event loops (root.mainloop() vs Toplevel()), causing the GUI to become unresponsive.
Main Code Block in operate.py:
if define_region: import tkinter as tk import queue import threading from operate.utils.area_selector import start_selection, create_outline_window print("Region definition mode activated.") coord_queue = queue.Queue() # Start the region selection process (runs in a separate thread) start_selection(coord_queue) # Function to periodically check the queue for selected coordinates def check_queue(): if not coord_queue.empty(): region = coord_queue.get() print(f"Selected region: {region}") # Open the red outline in a separate thread threading.Thread(target=create_outline_window, args=(root, region), daemon=True).start() # Close the region selection root root.quit() else: root.after(100, check_queue) # Create a Tkinter root for managing the selection root = tk.Tk() root.withdraw() check_queue() # Start queue checking root.mainloop() # Run the event looparea_selector.py; Selection Overlay
def select_area(coord_queue): root = tk.Tk() root.withdraw() overlay = tk.Toplevel(root) overlay.attributes('-topmost', True) overlay.attributes('-alpha', 0.3) overlay.overrideredirect(True) overlay.geometry(f"{root.winfo_screenwidth()}x{root.winfo_screenheight()}+0+0") # Red rectangle drawing logic canvas = tk.Canvas(overlay, cursor="cross", bd=0, highlightthickness=0) canvas.pack(fill=tk.BOTH, expand=True) rect = None def on_press(event): nonlocal rect rect = canvas.create_rectangle(event.x, event.y, event.x, event.y, outline='red', width=4) def on_drag(event): if rect: canvas.coords(rect, canvas.coords(rect)[0], canvas.coords(rect)[1], event.x, event.y) def on_release(event): coords = canvas.coords(rect) overlay.destroy() coord_queue.put(coords) root.quit() canvas.bind("<ButtonPress-1>", on_press) canvas.bind("<B1-Motion>", on_drag) canvas.bind("<ButtonRelease-1>", on_release) root.mainloop()I'm thinking the problem is:
Multiple Tkinter root windows?
I’m creating multiple Tk() and Toplevel() windows. Could these interfere with each other?
Mainloop Conflict:
I’m calling mainloop() in different threads and potentially mixing GUI contexts. Maybe I need a more synchronized approach?
Improper Thread Handling:
The selection overlay and outline window both use threading.Thread(). Perhaps I’m not handling thread termination properly?
The expected behavior is that it would keep the red outline there and move onto the next lines of code since it's multi-threaded. But it does not do that. Does anyone know how to resolve this?
Here's a video
The program stalls after the selection is made. The red outline is not persistent and must be exited to allow the program flow to keep going. I thought threading it would eliminate this flow issue and allow it to keep going, but it does not.
Here are the main files:
deanhystad write Jan-05-2025, 08:11 PM:
Please post all code, output and errors (it it's entirety) between their respective tags. Refer to BBCode help topic on how to post. Use the "Preview Post" button to make sure the code is presented as you expect before hitting the "Post Reply/Thread" button.
Please post all code, output and errors (it it's entirety) between their respective tags. Refer to BBCode help topic on how to post. Use the "Preview Post" button to make sure the code is presented as you expect before hitting the "Post Reply/Thread" button.