You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 09:07:32