Tkinter+CustomTkinter多窗口场景下幽灵点击与悬停事件串扰问题求助
Tkinter+CustomTkinter多窗口场景下幽灵点击与悬停事件串扰问题求助
我现在遇到了一个非常头疼的问题:在Tkinter+CustomTkinter的应用里打开第二个窗口后,出现了幽灵点击和悬停事件串扰的情况,想请教大家:
- 有没有办法正确隔离悬停和点击事件,让它们只作用于当前激活的窗口?
- 有没有和类相关的解决方案可以防止这种事件污染?
环境说明
我使用的是MacOS系统,Python版本为3.11,项目依赖Tkinter、CustomTkinter和TkinterDnD。
复现步骤
- 运行程序
- 点击“Phenotype Selection”按钮打开新窗口
- 点击主GUI的某个位置,优先选择窗口边缘区域
- 不要点击Phenotype Selection窗口,直接将鼠标移到它上面
发生的异常情况
- 即使光标停留在第二个窗口上,主GUI按钮的悬停效果仍会被触发
- 悬停和点击事件明显在窗口之间“泄露”了
- 主应用(MainApp)使用了
overrideredirect(True),需要手动处理悬停事件,但当另一个窗口打开时,它会错误识别鼠标位置
额外观察
- 第二个窗口没有使用
overrideredirect(True),自身行为完全正常 - 主GUI会错误地注册悬停事件,哪怕鼠标明明在第二个窗口的范围内
- 我们已经尝试了多种修复思路,但都没有解决问题
相关代码
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()
备注:内容来源于stack exchange,提问作者Chad Ify
相关产品推荐
相关产品推荐

