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

Tkinter生成参赛分组时出现重复分组问题求助

问题根源

你的脚本出现重复分组显示,核心原因是generate_pairings方法中连续调用了update_brackets()和create_placement_buttons()两个方法:

  • update_brackets()会在分组框架中生成仅显示成员名称的条目
  • create_placement_buttons()紧接着在同一个框架中生成带下拉菜单和记录按钮的完整分组条目
    两者叠加导致每组重复显示:一次无按钮,一次带按钮。

同时,原代码中create_placement_buttons方法没有先清空分组框架的旧内容,多次生成配对时还会累积旧分组;另外lambda表达式存在变量捕获问题,点击按钮时可能无法正确获取当前选择的排名。

修复方法

  1. 移除generate_pairings中的self.update_brackets()调用,让create_placement_buttons()单独负责渲染带操作按钮的分组
  2. 在create_placement_buttons开头添加清空分组框架的逻辑,避免旧内容累积
  3. 修正lambda表达式的变量捕获问题,确保每个按钮绑定正确的排名选择变量

修正后的核心代码片段

修改generate_pairings方法:

def generate_pairings(self):
    participants_copy = self.participants.copy()
    self.shuffle_participants()
    self.pair_participants()
    self.participants = participants_copy
    # 移除update_brackets调用,不再生成无按钮的分组
    self.create_placement_buttons()
    self.rounds = 1

修正create_placement_buttons方法:

def create_placement_buttons(self):
    # 先清空所有分组框架的旧内容
    for frame in self.bracket_frames:
        for widget in frame.winfo_children():
            widget.destroy()
    
    for i, pairing in enumerate(self.pairings):
        frame = self.bracket_frames[i]
        group_label = tk.Label(frame, text="Group {}".format(i+1), font=("Arial", 12, "bold"))
        group_label.pack()
        
        for j, participant in enumerate(pairing):
            entry_frame = tk.Frame(frame)
            entry_frame.pack()
            
            label = tk.Label(entry_frame, text=participant.get(), width=20)
            label.pack(side=tk.LEFT)
            
            options = ["First", "Second", "Third", "Fourth"]
            clicked = tk.StringVar()
            clicked.set("First")
            
            drop = tk.OptionMenu(entry_frame, clicked, *options)
            drop.pack(side=tk.LEFT)
            
            # 修正lambda变量捕获问题,将options和clicked作为参数传入
            button = tk.Button(entry_frame, text="Record Placement", 
                               command=lambda group_index=i, player_index=j, opt=options, var=clicked: 
                               self.record_placement(group_index, player_index, opt.index(var.get()) + 1))
            button.pack(side=tk.LEFT)

完整修正后的代码

import tkinter as tk
from tkinter import messagebox
import random

class TournamentApp(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("Tournament App")
        self.geometry("800x600")
        
        self.participants = []
        self.rounds = 0
        self.pairings = []
        self.results = {}
        
        self.entry_frame = tk.Frame(self)
        self.entry_frame.pack(pady=10)
        self.entry_frame.place(x=100, y=25)
        
        self.round_frame = tk.Frame(self)
        self.round_frame.pack(pady=10)
        
        self.round_label = tk.Label(self.round_frame, text="Round 1")
        self.round_label.pack()
        
        self.results_frame = tk.Frame(self)
        self.results_frame.pack(pady=10)
        self.results_frame.place(x=1100, y=25)
        
        self.results_label = tk.Label(self.results_frame, text="Results")
        self.results_label.pack()
        
        self.win_loss_frame = tk.Frame(self)
        self.win_loss_frame.pack(pady=10)
        
        self.create_entry_fields()
        self.create_pairings_button()
        self.create_round_button()
        self.create_results_table()
        self.create_bracket_label()
        self.create_bracket_frames()
        self.create_reset_button()

    def create_entry_fields(self):
        entry_label = tk.Label(self.entry_frame, text="Enter participant names:")
        entry_label.place(x=400, y=100)
        entry_label.pack()
        
        for i in range(12):
            entry = tk.Entry(self.entry_frame)
            entry.pack(pady=5)
            self.participants.append(entry)
            
    def create_pairings_button(self):
        pairings_button = tk.Button(self, text="Generate Pairings", command=self.generate_pairings)
        pairings_button.pack(pady=10)
        
    def create_round_button(self):
        round_button = tk.Button(self, text="Start New Round", command=self.start_new_round)
        round_button.pack(pady=10)
        
    def create_results_table(self):
        self.results_table = tk.Label(self.results_frame, text="")
        self.results_table.pack()
        
    def create_bracket_label(self):
        bracket_label = tk.Label(self, text="Generated Pairings")
        bracket_label.pack()
        
    def create_bracket_frames(self):
        self.bracket_frame = tk.Frame(self)
        self.bracket_frame.pack(pady=10)
        
        self.bracket_frames = []
        
        for i in range(4):
            frame = tk.Frame(self.bracket_frame)
            frame.grid(row=i, column=0, padx=10)
            self.bracket_frames.append(frame)
        
    def generate_pairings(self):
        participants_copy = self.participants.copy()
        self.shuffle_participants()
        self.pair_participants()
        self.participants = participants_copy
        self.create_placement_buttons()
        self.rounds = 1


    def shuffle_participants(self):
        shuffled_participants = self.participants.copy()
        random.shuffle(shuffled_participants)
        self.participants = shuffled_participants

        
    def pair_participants(self):
        min_players_per_group = 4
        max_players_per_group = 4

        num_players = len(self.participants)
        if num_players < min_players_per_group:
            messagebox.showwarning("Insufficient Players", "At least {} players are required.".format(min_players_per_group))
            return

        self.pairings = []
        group_pairing = []

        for i, participant in enumerate(self.participants):
            if participant.get().strip():
                group_pairing.append(participant)

            if len(group_pairing) == max_players_per_group or i == num_players - 1:
                self.pairings.append(group_pairing)
                group_pairing = []

        if group_pairing:
            self.pairings.append(group_pairing)
        
    def start_new_round(self):
        if self.rounds > 0:
            self.update_results_table()
            
        self.rounds += 1
        self.round_label.config(text="Round {}".format(self.rounds))
        
    def record_placement(self, group_index, player_index, placement):
        group_pairing = self.pairings[group_index]
        participant = group_pairing[player_index].get()
        
        if participant not in self.results:
            self.results[participant] = {
                "1st Place": 0,
                "2nd Place": 0,
                "3rd Place": 0,
                "4th Place": 0
            }
        
        if placement == 1:
            self.results[participant]["1st Place"] += 1
        elif placement == 2:
            self.results[participant]["2nd Place"] += 1
        elif placement == 3:
            self.results[participant]["3rd Place"] += 1
        elif placement == 4:
            self.results[participant]["4th Place"] += 1
        
        self.update_results_table()
        
    def update_results_table(self):
        results_text = "Results after Round {}:\n\n".format(self.rounds)
        
        for participant, data in self.results.items():
            results_text += "{}: 1st Place: {}, 2nd Place: {}, 3rd Place: {}, 4th Place: {}\n".format(
                participant, data["1st Place"], data["2nd Place"], data["3rd Place"], data["4th Place"]
            )
        
        self.results_table.config(text=results_text)

    def create_placement_buttons(self):
        for frame in self.bracket_frames:
            for widget in frame.winfo_children():
                widget.destroy()
        
        for i, pairing in enumerate(self.pairings):
            frame = self.bracket_frames[i]
            group_label = tk.Label(frame, text="Group {}".format(i+1), font=("Arial", 12, "bold"))
            group_label.pack()
            
            for j, participant in enumerate(pairing):
                entry_frame = tk.Frame(frame)
                entry_frame.pack()
                
                label = tk.Label(entry_frame, text=participant.get(), width=20)
                label.pack(side=tk.LEFT)
                
                options = ["First", "Second", "Third", "Fourth"]
                clicked = tk.StringVar()
                clicked.set("First")
                
                drop = tk.OptionMenu(entry_frame, clicked, *options)
                drop.pack(side=tk.LEFT)
                
                button = tk.Button(entry_frame, text="Record Placement", 
                                   command=lambda group_index=i, player_index=j, opt=options, var=clicked: 
                                   self.record_placement(group_index, player_index, opt.index(var.get()) + 1))
                button.pack(side=tk.LEFT)

    def create_reset_button(self):
        reset_button = tk.Button(self, text="Reset", command=self.reset)
        reset_button.place(x=10, y=10)
        
    def reset(self):
        self.participants = []
        self.rounds = 0
        self.pairings = []
        self.results = {}
        
        for frame in self.bracket_frames:
            for widget in frame.winfo_children():
                widget.destroy()
        
        self.round_label.config(text="Round 1")
        self.results_table.config(text="")
        
        for entry in self.entry_frame.winfo_children():
            entry.destroy()

        self.create_entry_fields()

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

内容的提问来源于stack exchange,提问作者Matt Owens

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 21:42:00