[Python] Phantom click and hover issue when opening a second window in my Tkinter +...

Discussão em 'Python' iniciado por Stack, Fevereiro 7, 2025.

  1. Stack

    Stack Membro Participativo


    • Is there a way to properly isolate hover and click events so that they only apply to the currently active window?


    • Is there some class-related solution that can prevent this event contamination?

    I’m encountering a phantom click and hover issue when opening a second window in my Tkinter + CustomTkinter application.

    Please note: I am working with MacOS and my Python Version is 3.11.

    Steps to Reproduce the Issue:

    1. Run the program.
    2. Click the "Phenotype Selection" button to open the new window.
    3. Click somewhere on the main GUI, preferably on the edge of the window.
    4. Without clicking inside the Phenotype Selection window, move your mouse over it.

    What Happens:

    1. The hover effects from the main GUI's buttons get triggered even though the cursor is on the second window.
    2. It appears that hover and click events are leaking between windows.
    3. The main application (MainApp) uses overrideredirect(True), meaning it manually handles hover events, but it gets confused when another window is open.

    Additional Observations:

    1. The second window does not use overrideredirect(True), and it behaves normally.
    2. However, the main GUI starts incorrectly registering hover events, even though the mouse is on the second window.
    3. We have tried multiple fixes, but nothing has worked.

    import tkinter as tk
    import customtkinter as ctk
    from tkinterdnd2 import DND_FILES, TkinterDnD # Use this import for drag-and-drop support

    ctk.set_appearance_mode("Dark")
    ctk.set_default_color_theme("blue")

    class LayoutBarApp(ctk.CTkFrame):
    """ Main Layout Bar with custom buttons. """
    def __init__(self, parent):
    super().__init__(parent)
    self.pack_propagate(False)
    self.pack(side="top", fill="x")
    self.active_button = None
    self.buttons = {}

    # Create layout buttons
    self.create_layout_buttons()

    def open_phenotype_selection_window(self):
    """ Opens a new window for Phenotype Selection. """
    if hasattr(self, "phenotype_window") and self.phenotype_window.winfo_exists():
    self.phenotype_window.lift() # Bring existing window to front
    return

    self.phenotype_window = ctk.CTkToplevel(self) # Use CTkToplevel for consistency with CTk
    self.phenotype_window.title("Phenotype Selection")
    self.phenotype_window.geometry("400x300+400+100") # Adjust size/position as needed
    self.phenotype_window.resizable(False, False)

    # Add a label
    label = ctk.CTkLabel(self.phenotype_window, text="Select Phenotype", font=("Arial", 16, "bold"))
    label.pack(pady=10)

    # Example: Button inside the new window
    close_button = ctk.CTkButton(self.phenotype_window, text="Close", command=self.phenotype_window.destroy)
    close_button.pack(pady=10)


    def create_layout_buttons(self):
    """ Create buttons with their icons and commands. """
    button_actions = {
    "Order Search": None,
    "Phenotype Selection": self.open_phenotype_selection_window, # ✅ Assigned function
    "Bounding Box": None,
    "Landmark Movement": None,
    "Face Measurement": None,
    }

    for btn_text, action in button_actions.items():

    button = ctk.CTkButton(
    self,
    text=btn_text.replace(" ", "\n"),
    command=lambda b=btn_text, action=action: self.activate_button(b, action), # ✅ Corrected lambda

    fg_color=("#3b8ed0", "#1f6aa5"),
    hover_color=("#2a75c0", "#155a8a")
    )
    button.pack(side="left", padx=(5, 0), pady=5)
    self.buttons[btn_text] = button


    def activate_button(self, button_name, action):
    """ Handles button activation (highlighting) and executes the assigned action. """

    # ✅ Get the actual root coordinates to adjust hover issues
    root_x = self.winfo_rootx()
    root_y = self.winfo_rooty()

    mouse_x = self.winfo_pointerx() - root_x
    mouse_y = self.winfo_pointery() - root_y

    print(f"Mouse Position Adjusted: ({mouse_x}, {mouse_y}), Button:{button_name} Self:{self}, Action{action}") # ✅ Debugging hover issue

    # Reset previous button color
    if self.active_button:
    self.buttons[self.active_button].configure(
    fg_color=("#3b8ed0", "#1f6aa5"),
    hover_color=("#2a75c0", "#155a8a")
    )

    # Set new active button
    self.active_button = button_name
    self.buttons[button_name].configure(
    fg_color="green",
    hover_color="#006400"
    )
    # Execute the function if it exists
    if action:
    action()

    class MainApp(TkinterDnD.Tk):
    """ Root Tkinter App holding both Sidebar and Layout Bar. """
    def __init__(self):
    super().__init__()

    self.overrideredirect(True) # Removes system title bar
    self.geometry("782x60+330+0")
    self.resizable(False, False)
    self.title("GUI")

    # Main Layout Bar
    self.layout_bar = LayoutBarApp(self)

    if __name__ == "__main__":
    app = MainApp()
    app.mainloop()

    Continue reading...

Compartilhe esta Página