Tkinter窗口最大化时误触发按钮点击的问题求助
问题描述
我希望仅在点击按钮时执行button_clicked()函数打印Market ID和Player ID,但双击Windows窗口边缘的蓝色区域进行垂直最大化时,会误触发标注为Roger Federer的按钮点击事件,需要找到仅在点击按钮时才执行函数的解决方法。
成因分析
在Windows系统中,双击窗口边缘触发最大化操作时,窗口管理器会发送鼠标事件到窗口的特定位置。当窗口大小变化导致内部组件重新布局后,Roger Federer按钮的位置恰好与该鼠标事件的位置重合,从而被误判为按钮点击事件。此外,Tkinter的组件重排逻辑在窗口尺寸变更时,可能会让组件意外捕获到非用户主动触发的鼠标事件。
解决方案
通过将按钮的命令绑定从command参数改为直接绑定<Button-1>事件(即鼠标左键点击事件),确保只有用户主动点击按钮时才触发button_clicked()函数,避免窗口调整时的误触发。
修正后的Pandas版本代码
from functools import partial import tkinter as tk import pandas as pd def button_clicked(market_id, player_id): print("Market ID:", market_id) print("Player ID:", player_id) def create_window(dataframe): window = tk.Tk() window.title("Tennis Matches") window_width = 400 window_height = min(len(dataframe) * 50 + 100, 400) window.geometry(f"{window_width}x{window_height}") window.configure(bg="white") canvas = tk.Canvas(window, bg="white") canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) scrollbar = tk.Scrollbar(window, orient=tk.VERTICAL, command=canvas.yview) scrollbar.pack(side=tk.RIGHT, fill=tk.Y) canvas.configure(yscrollcommand=scrollbar.set) frame = tk.Frame(canvas, bg="white") canvas.create_window((0, 0), window=frame, anchor='nw') max_button_text_length = max( max(dataframe['player_one_name'].apply(len)), max(dataframe['player_two_name'].apply(len)) ) for index, row in dataframe.iterrows(): game_label = tk.Label(frame, text=row['match_name'], bg="white", fg="black") game_label.pack() button_frame = tk.Frame(frame, bg="white") button_frame.pack() # 替换command参数为绑定<Button-1>事件 button1 = tk.Button(button_frame, text=row['player_one_name'], bg="white", fg="black") button1.bind("<Button-1>", lambda e, mid=row['market_id'], pid=row['player_one_id']: button_clicked(mid, pid)) button1.pack(side=tk.LEFT, padx=5) button1.config(width=max_button_text_length, borderwidth=2, font=('Arial', 10, 'bold')) button2 = tk.Button(button_frame, text=row['player_two_name'], bg="white", fg="black") button2.bind("<Button-1>", lambda e, mid=row['market_id'], pid=row['player_two_id']: button_clicked(mid, pid)) button2.pack(side=tk.LEFT, padx=5) button2.config(width=max_button_text_length, borderwidth=2, font=('Arial', 10, 'bold')) button1.config(anchor="center") button2.config(anchor="center") separator = tk.Frame(frame, height=2, bd=1, relief=tk.SUNKEN, bg="white") separator.pack(fill=tk.X, padx=5, pady=5) def on_configure(event): canvas.configure(scrollregion=canvas.bbox('all')) frame.bind('<Configure>', on_configure) def _on_mousewheel(event): canvas.yview_scroll(int(-1 * (event.delta / 120)), "units") canvas.bind_all("<MouseWheel>", _on_mousewheel) window.mainloop() data = { 'match_name': ['Aberto da Austrália - Rafael Nadal x Roger Federer', 'Wimbledon - Novak Djokovic x Andy Murray', 'Aberto da França - Serena Williams x Simona Halep', 'US Open - Naomi Osaka x Ashleigh Barty', 'Aberto da Austrália - Dominic Thiem x Alexander Zverev', 'Wimbledon - Stefanos Tsitsipas x Matteo Berrettini', 'Aberto da França - Iga Swiatek x Elina Svitolina', 'US Open - Bianca Andreescu x Karolina Pliskova'], 'market_id': [1, 2, 3, 4, 5, 6, 7, 8], 'player_one_name': ['Rafael Nadal', 'Novak Djokovic', 'Serena Williams', 'Naomi Osaka', 'Dominic Thiem', 'Stefanos Tsitsipas', 'Iga Swiatek', 'Bianca Andreescu'], 'player_one_id': [1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008], 'player_two_name': ['Roger Federer', 'Andy Murray', 'Simona Halep', 'Ashleigh Barty', 'Alexander Zverev', 'Matteo Berrettini', 'Elina Svitolina', 'Karolina Pliskova'], 'player_two_id': [2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008] } df = pd.DataFrame(data) create_window(df)
修正后的无Pandas版本代码
import tkinter as tk def button_clicked(market_id, player_id): print("Market ID:", market_id) print("Player ID:", player_id) def create_window(data): window = tk.Tk() window.title("Tennis Matches") window_width = 400 window_height = min(len(data['match_name']) * 50 + 100, 400) window.geometry(f"{window_width}x{window_height}") window.configure(bg="white") canvas = tk.Canvas(window, bg="white") canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) scrollbar = tk.Scrollbar(window, orient=tk.VERTICAL, command=canvas.yview) scrollbar.pack(side=tk.RIGHT, fill=tk.Y) canvas.configure(yscrollcommand=scrollbar.set) frame = tk.Frame(canvas, bg="white") canvas.create_window((0, 0), window=frame, anchor='nw') max_button_text_length = max( max(len(name) for name in data['player_one_name']), max(len(name) for name in data['player_two_name']) ) for i in range(len(data['match_name'])): game_label = tk.Label(frame, text=data['match_name'][i], bg="white", fg="black") game_label.pack() button_frame = tk.Frame(frame, bg="white") button_frame.pack() # 替换command参数为绑定<Button-1>事件 button1 = tk.Button(button_frame, text=data['player_one_name'][i], bg="white", fg="black") button1.bind("<Button-1>", lambda e, i=i: button_clicked(data['market_id'][i], data['player_one_id'][i])) button1.pack(side=tk.LEFT, padx=5) button1.config(width=max_button_text_length, borderwidth=2, font=('Arial', 10, 'bold')) button2 = tk.Button(button_frame, text=data['player_two_name'][i], bg="white", fg="black") button2.bind("<Button-1>", lambda e, i=i: button_clicked(data['market_id'][i], data['player_two_id'][i])) button2.pack(side=tk.LEFT, padx=5) button2.config(width=max_button_text_length, borderwidth=2, font=('Arial', 10, 'bold')) button1.config(anchor="center") button2.config(anchor="center") separator = tk.Frame(frame, height=2, bd=1, relief=tk.SUNKEN, bg="white") separator.pack(fill=tk.X, padx=5, pady=5) def on_configure(event): canvas.configure(scrollregion=canvas.bbox('all')) frame.bind('<Configure>', on_configure) def _on_mousewheel(event): canvas.yview_scroll(int(-1 * (event.delta / 120)), "units") canvas.bind_all("<MouseWheel>", _on_mousewheel) window.mainloop() data = { 'match_name': ['Aberto da Austrália - Rafael Nadal x Roger Federer', 'Wimbledon - Novak Djokovic x Andy Murray', 'Aberto da França - Serena Williams x Simona Halep', 'US Open - Naomi Osaka x Ashleigh Barty', 'Aberto da Austrália - Dominic Thiem x Alexander Zverev', 'Wimbledon - Stefanos Tsitsipas x Matteo Berrettini', 'Aberto da França - Iga Swiatek x Elina Svitolina', 'US Open - Bianca Andreescu x Karolina Pliskova'], 'market_id': [1, 2, 3, 4, 5, 6, 7, 8], 'player_one_name': ['Rafael Nadal', 'Novak Djokovic', 'Serena Williams', 'Naomi Osaka', 'Dominic Thiem', 'Stefanos Tsitsipas', 'Iga Swiatek', 'Bianca Andreescu'], 'player_one_id': [1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008], 'player_two_name': ['Roger Federer', 'Andy Murray', 'Simona Halep', 'Ashleigh Barty', 'Alexander Zverev', 'Matteo Berrettini', 'Elina Svitolina', 'Karolina Pliskova'], 'player_two_id': [2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008] } create_window(data)
内容的提问来源于stack exchange,提问作者Digital Farmer
相关产品推荐
相关产品推荐

