首页 > 编程语言 >Python-开发运动会计分管理软件

Python-开发运动会计分管理软件

时间:2024-11-19 20:19:03浏览次数:3  
标签:group 计分 Python athlete window 管理软件 score tk self

PYTHON-开发运动会计分管理软件

项目概述

1. 软件功能

我们的运动会计分管理软件具有以下功能:

  • 添加运动员:提供接口让用户输入运动员的基本信息,包括分组、姓名、名次。
  • 管理分组:支持创建、修改和删除运动员分组,方便组织和查看。
  • 得分计算:根据运动员名次自动计算得分,并在用户界面中更新。
  • 查看总分:统计所有运动员的总分、平均分、最高分和最低分,并支持分组汇总。
  • 数据导出:允许用户将所有运动员信息导出为 CSV 文件,便于存档和后续使用。
  • 切换破纪录状态:通过右键菜单允许用户方便地切换运动员的破纪录状态,影响得分计算。

2. 技术栈

本项目所需的技术栈包括:

  • Python:作为编程语言实现逻辑和数据处理。
  • tkinter:构建图形用户界面,快速开发桌面应用。
  • CSV模块:用于处理数据导出与导入的标准库。

3. 软件开发环境

开发此软件时,需确保您的计算机上安装了 Python(建议使用 Python 3.7 及以上版本)。同时,我们使用的 tkinter 库是 Python 的标准库,不需要单独安装。CSV模块也是Python自带的模块,您可以直接使用。

安装与基础设置

  1. 安装 Python

    • 前往 Python 官网 下载并安装适合您操作系统的版本。请确保勾选“Add Python to PATH”的选项。
  2. 创建项目文件夹

    • 在您的计算机上创建一个新的文件夹,命名为 ScoreManagementApp,在其中创建一个文件 score_app.py,并在里面编写代码。
  3. 环境配置

    • 在终端中使用 pip 安装所需的第三方库(如有需要)。本项目不依赖于外部库,直接使用tkintercsv标准库。

开发步骤详解

1. 数据结构设计

通过使用数据类 (dataclass) 来定义运动员的信息结构,使得数据的管理和访问更加方便。

from dataclasses import dataclass

@dataclass
class Athlete:
    group: str
    name: str
    rank: int
    score: int
    is_record: bool = False

上述代码简洁地定义了运动员的各种属性,包括其所属分组、姓名、名次、得分和破纪录状态。使用数据类的好处是可以更直观地管理运动员信息,并提升代码的可读性。

2. 创建主应用程序类 ScoreApp

以下是实现 ScoreApp 类的基本框架和关键功能。该类负责所有界面组件的管理以及实现各项业务逻辑。

import tkinter as tk
from tkinter import ttk, messagebox, filedialog, Menu, OptionMenu, StringVar
import csv

class ScoreApp:
    def __init__(self, root):
        self.root = root
        self.root.title("运动会计分管理软件")

        # 初始化名次和分数对应关系
        self.rank_to_score = {1: 9, 2: 7, 3: 6, 4: 5, 5: 4, 6: 3, 7: 2, 8: 1}

        # 可用分组
        self.available_groups = {"组A"}

        # 表格呈现运动员信息
        self.tree = ttk.Treeview(root, columns=("分组", "姓名", "名次", "分数", "破纪录"), show='headings')
        self.setup_treeview()

        # 控件布局和功能定义
        self.setup_controls()

        # 初始化运动员列表
        self.scores = []
        self.group_filter_var = StringVar(root)
        self.group_filter_var.set("所有分组")
        self.setup_group_selection()

    def setup_treeview(self):
        """ 设置Treeview组件 """
        self.tree.heading("分组", text="分组")
        self.tree.heading("姓名", text="姓名")
        self.tree.heading("名次", text="名次")
        self.tree.heading("分数", text="分数")
        self.tree.heading("破纪录", text="破纪录")

        for col in ("分组", "姓名", "名次", "分数", "破纪录"):
            self.tree.column(col, width=100)

        self.tree.grid(row=0, column=0, columnspan=5, padx=10, pady=10)

    def setup_controls(self):
        """ 创建按钮和控制框 """
        tk.Button(self.root, text="添加运动员", command=self.open_add_athlete_dialog).grid(row=1, column=0, padx=5, pady=5)
        tk.Button(self.root, text="管理分组", command=self.open_group_management).grid(row=1, column=1, padx=5, pady=5)
        tk.Button(self.root, text="查看总分", command=self.view_total_scores).grid(row=1, column=2, padx=5, pady=5)
        tk.Button(self.root, text="导出数据", command=self.export_to_csv).grid(row=1, column=3, padx=5, pady=5)
        tk.Button(self.root, text="删除选中行", command=self.delete_selected).grid(row=1, column=4, padx=5, pady=5)
        tk.Button(self.root, text="设置分数", command=self.open_settings).grid(row=1, column=5, padx=5, pady=5)

    def setup_group_selection(self):
        """ 设置分组选择下拉框 """
        # 分组选择实现略

上述代码展示了如何初始化应用程序的窗口并构建基本元素,比如设置表格(Treeview)和按钮。设计时需要确保用户界面友好,并能方便地访问不同功能。

3. 添加运动员信息

添加运动员的对话框包括必要的输入字段,并在用户确认后将数据录入到列表中。

def open_add_athlete_dialog(self):
    """ 打开添加运动员的对话框 """
    add_window = tk.Toplevel(self.root)
    add_window.title("添加运动员")

    tk.Label(add_window, text="分组:").grid(row=0, column=0, padx=10, pady=5)
    group_entry = StringVar(add_window)
    group_entry.set("选择分组或自定义")
    group_menu = OptionMenu(add_window, group_entry, *self.available_groups)
    group_menu.grid(row=0, column=1, padx=10, pady=5)

    tk.Label(add_window, text="姓名:").grid(row=1, column=0, padx=10, pady=5)
    name_entry = tk.Entry(add_window)
    name_entry.grid(row=1, column=1, padx=10, pady=5)

    tk.Label(add_window, text="名次:").grid(row=2, column=0, padx=10, pady=5)
    rank_entry = tk.Entry(add_window)
    rank_entry.grid(row=2, column=1, padx=10, pady=5)

    tk.Button(add_window, text="确认", command=lambda: self.add_score(group_entry.get(), name_entry.get(), rank_entry.get(), add_window)).grid(row=3, columnspan=3, pady=10)

def add_score(self, group, name, rank_str, add_window):
    """ 添加运动员信息 """
    if group and name and rank_str.isdigit() and int(rank_str) in self.rank_to_score:
        rank = int(rank_str)
        score = self.rank_to_score[rank]
        athlete = Athlete(group, name, rank, score)
        self.scores.append(athlete)
        self.tree.insert("", "end", values=(athlete.group, athlete.name, athlete.rank, athlete.score, "✔" if athlete.is_record else "✖"))
        add_window.destroy()
    else:
        messagebox.showwarning("输入错误", "请确保所有输入有效!")

open_add_athlete_dialog 方法负责展示添加运动员信息的输入窗口,而 add_score 方法则实现将输入的运动员信息添加到数据结构和界面表格中。输入验证确保数据的有效性,避免无效的输入占用系统资源。

4. 查看总分和数据导出

审核和导出运动员总分也是软件必不可少的功能。我们将通过一个弹出的新窗口展示统计数据,并支持将数据导出为 CSV 格式以备存档。

def view_total_scores(self):
    total_window = tk.Toplevel(self.root)
    total_window.title("总分")

    total_label = tk.Label(total_window, text="所有运动员总分:")
    total_label.pack(padx=10, pady=5)

    total_score = sum(athlete.score * (2 if athlete.is_record else 1) for athlete in self.scores)
    all_scores_label = tk.Label(total_window, text=f"总分: {total_score}")
    all_scores_label.pack(padx=10, pady=5)

    # 计算和展示平均分、最高分、最低分
    average_score = total_score / len(self.scores) if self.scores else 0
    highest_score = max(athlete.score for athlete in self.scores) if self.scores else 0
    lowest_score = min(athlete.score for athlete in self.scores) if self.scores else 0

    stats_label = tk.Label(total_window, text=f"平均分: {average_score:.2f}, 最高分: {highest_score}, 最低分: {lowest_score}")
    stats_label.pack(padx=10, pady=5)

def export_to_csv(self):
    filename = filedialog.asksaveasfilename(defaultextension=".csv", filetypes=[("CSV files", "*.csv")])
    if filename:
        with open(filename, mode='w', newline='', encoding='utf-8') as file:
            writer = csv.writer(file)
            writer.writerow(["分组", "姓名", "名次", "分数", "破纪录"])
            for athlete in self.scores:
                writer.writerow([athlete.group, athlete.name, athlete.rank, athlete.score, athlete.is_record])
        messagebox.showinfo("成功", f"数据已导出到 {filename}")

view_total_scores 方法计算所有运动员的分数,并将其展示在新窗口中,而 export_to_csv 则构建 CSV 文件并保存用户指定的位置。此功能对于后续的数据分析和管理至关重要,帮助用户轻松整理和传递信息。

5. 管理分组和删除运动员

用户需要能够动态地管理运动员组和删除不再需要的运动员记录。以下是相关的实现:

def open_group_management(self):
    group_window = tk.Toplevel(self.root)
    group_window.title("管理分组")

    tk.Label(group_window, text="自定义分组:").grid(row=0, column=0, padx=10, pady=5)
    custom_group_entry = tk.Entry(group_window)
    custom_group_entry.grid(row=0, column=1, padx=10, pady=5)
    tk.Button(group_window, text="添加分组", command=lambda: self.add_custom_group(custom_group_entry.get())).grid(row=0, column=2, padx=10, pady=5)

    tk.Label(group_window, text="当前分组:").grid(row=1, column=0, padx=10, pady=5)
    current_groups_var = StringVar(value=", ".join(sorted(self.available_groups)))
    tk.Entry(group_window, textvariable=current_groups_var, state='readonly').grid(row=1, column=1, padx=10, pady=5)

    tk.Label(group_window, text="删除分组:").grid(row=2, column=0, padx=10, pady=5)
    delete_group_entry = tk.Entry(group_window)
    delete_group_entry.grid(row=2, column=1, padx=10, pady=5)

    tk.Button(group_window, text="删除分组", command=lambda: self.delete_custom_group(delete_group_entry.get())).grid(row=2, column=2, padx=10, pady=5)

def add_custom_group(self, group_name):
    if group_name and group_name not in self.available_groups:
        self.available_groups.add(group_name)
        self.setup_group_selection()
        messagebox.showinfo("成功", f"已添加自定义分组: {group_name}")

def delete_selected(self):
    selected_item = self.tree.selection()
    if selected_item:
        for item in selected_item:
            index = self.tree.index(item)
            self.tree.delete(item)
            del self.scores[index]
        self.update_displayed_athletes()
    else:
        messagebox.showwarning("选择错误", "请先选择一行!")

open_group_management 方法启用分组的添加和删除,增强了对运动员的组织能力,而 delete_selected 则允许用户删除选中的运动员记录,使得整体管理变得灵活。

6. 用户交互的多样性

在软件中,右键菜单为用户提供了灵活的操作手段,比如切换运动员的破纪录状态。调用右键菜单的相关实现代码如下:

def show_popup(self, event):
    try:
        selected = self.tree.identify_row(event.y)
        if selected:
            self.tree.selection_set(selected)
            self.popup_menu.post(event.x_root, event.y_root)
    except Exception as e:
        print(f"Error showing popup menu: {e}")

self.popup_menu = Menu(root, tearoff=0)
self.popup_menu.add_command(label="切换破纪录", command=self.toggle_record)

通过实现相应的事件绑定,我们使得软件的交互性更强,更加贴合用户的操作习惯。

7. 代码结构与模块化

在整个应用中,保持良好的代码结构和模块化设计是至关重要的。这不仅能提升代码的可读性,还能帮助团队中的其他开发者快速理解和修改代码。

可以将不同的功能区域分开为不同的模块,例如将与数据存储、数据处理、用户界面等相关的功能分别放入不同的文件中。使用 Python 的模块导入功能来连接这些组件,可以有效管理大型项目,提升维护性。

总结

本篇博客详细介绍了如何使用 Python 的 tkinter 库创建一个运动会计分管理软件。

作为示例为研究GUI和数据结构打下基础

完整源码:

import tkinter as tk
from tkinter import ttk, simpledialog, messagebox, Menu, OptionMenu, StringVar, filedialog
from dataclasses import dataclass
import csv

# 数据类: 运动员信息
@dataclass
class Athlete:
    group: str
    name: str
    rank: int
    score: int
    is_record: bool = False

class ScoreApp:
    def __init__(self, root):
        self.root = root
        self.root.title("运动会计分软件")
        
        # 默认名次与分数对应关系
        self.rank_to_score = {
            1: 9,
            2: 7,
            3: 6,
            4: 5,
            5: 4,
            6: 3,
            7: 2,
            8: 1
        }

        # 可用分组
        self.available_groups = {"组A"}  # 默认分组

        # 表格呈现
        self.tree = ttk.Treeview(root, columns=("分组", "姓名", "名次", "分数", "破纪录"), show='headings')
        self.tree.heading("分组", text="分组")
        self.tree.heading("姓名", text="姓名")
        self.tree.heading("名次", text="名次")
        self.tree.heading("分数", text="分数")
        self.tree.heading("破纪录", text="破纪录")
        
        self.tree.column("分组", width=100)
        self.tree.column("姓名", width=200)
        self.tree.column("名次", width=100)
        self.tree.column("分数", width=100)
        self.tree.column("破纪录", width=100)

        self.tree.grid(row=0, column=0, columnspan=5, padx=10, pady=10)

        # 添加按钮
        self.add_button = tk.Button(root, text="添加运动员", command=self.open_add_athlete_dialog)
        self.add_button.grid(row=1, column=0, padx=5, pady=5)

        # 管理分组按钮
        self.group_management_button = tk.Button(root, text="管理分组", command=self.open_group_management)
        self.group_management_button.grid(row=1, column=1, padx=5, pady=5)

        # 查看总分按钮
        self.total_button = tk.Button(root, text="查看总分", command=self.view_total_scores)
        self.total_button.grid(row=1, column=2, padx=5, pady=5)

        # 导出按钮
        self.export_button = tk.Button(root, text="导出数据", command=self.export_to_csv)
        self.export_button.grid(row=1, column=3, padx=5, pady=5)

        # 删除按钮
        self.delete_button = tk.Button(root, text="删除选中行", command=self.delete_selected)
        self.delete_button.grid(row=1, column=4, padx=5, pady=5)

        # 设置按钮
        self.settings_button = tk.Button(root, text="设置分数", command=self.open_settings)
        self.settings_button.grid(row=1, column=5, padx=5, pady=5)

        # 右键菜单
        self.popup_menu = Menu(root, tearoff=0)
        self.popup_menu.add_command(label="切换破纪录", command=self.toggle_record)
        self.popup_menu.add_separator()
        # 这里调用 open_group_management
        self.popup_menu.add_command(label="设置分组", command=self.open_group_management)


        # 绑定右键点击
        self.tree.bind("<Button-3>", self.show_popup)

        # 运动员信息列表
        self.scores = []

        # 分组过滤变量
        self.group_filter_var = StringVar(root)
        self.group_filter_var.set("所有分组")
        self.setup_group_selection()

    def setup_group_selection(self):
        """ 设置和显示分组选择下拉框 """
        groups = sorted(self.available_groups) + ["所有分组"]
        group_menu = OptionMenu(self.root, self.group_filter_var, *groups, command=self.update_displayed_athletes)
        group_menu.grid(row=1, column=6, padx=5, pady=5)

    def update_displayed_athletes(self, *args):
        """ 根据选择的分组更新显示的运动员 """
        self.tree.delete(*self.tree.get_children())
        filtered_scores = [athlete for athlete in self.scores if self.group_filter_var.get() in ("所有分组", athlete.group)]
        for athlete in filtered_scores:
            self.tree.insert("", "end", values=(athlete.group, athlete.name, athlete.rank, athlete.score, "✔" if athlete.is_record else "✖"))

    def open_add_athlete_dialog(self):
        """ 打开添加运动员的对话框 """
        add_window = tk.Toplevel(self.root)
        add_window.title("添加运动员")

        # 输入字段
        tk.Label(add_window, text="分组:").grid(row=0, column=0, padx=10, pady=5)
        group_entry = StringVar(add_window)
        group_entry.set("选择分组或自定义")
        group_menu = OptionMenu(add_window, group_entry, *self.available_groups)
        group_menu.grid(row=0, column=1, padx=10, pady=5)
        custom_group_entry = tk.Entry(add_window)  # 自定义分组输入
        custom_group_entry.grid(row=0, column=2, padx=10, pady=5)

        tk.Label(add_window, text="姓名:").grid(row=1, column=0, padx=10, pady=5)
        name_entry = tk.Entry(add_window)
        name_entry.grid(row=1, column=1, padx=10, pady=5)

        tk.Label(add_window, text="名次:").grid(row=2, column=0, padx=10, pady=5)
        rank_entry = tk.Entry(add_window)
        rank_entry.grid(row=2, column=1, padx=10, pady=5)

        # 确认按钮
        tk.Button(add_window, text="确认", command=lambda: self.add_score(custom_group_entry.get(), group_entry.get(), name_entry.get(), rank_entry.get(), add_window)).grid(row=3, columnspan=3, pady=10)

    def add_score(self, custom_group, group, name, rank_str, add_window):
        """ 添加运动员信息 """
        group_to_use = custom_group if custom_group else group
        if group_to_use and name and rank_str.isdigit() and int(rank_str) in self.rank_to_score:
            rank = int(rank_str)
            score = self.rank_to_score[rank]
            athlete = Athlete(group_to_use, name, rank, score)  # 使用数据类
            self.scores.append(athlete)  # 添加运动员
            self.tree.insert("", "end", values=(athlete.group, athlete.name, athlete.rank, athlete.score, "✔" if athlete.is_record else "✖"))
            add_window.destroy()  # 关闭添加窗口
            self.sort_treeview()  # 添加后自动排序
            self.available_groups.add(group_to_use)  # 自定义分组添加到集合
            self.setup_group_selection()  # 更新分组选择

        else:
            messagebox.showwarning("输入错误", "请确保所有输入有效!")

    def sort_treeview(self):
        """ 按照分数从高到低排序 """
        sorted_scores = sorted(self.scores, key=lambda x: x.score, reverse=True)
        self.tree.delete(*self.tree.get_children())  # 清空当前显示的所有行

        # 重新显示排序后的运动员信息
        for athlete in sorted_scores:
            self.tree.insert("", "end", values=(athlete.group, athlete.name, athlete.rank, athlete.score, "✔" if athlete.is_record else "✖"))

    def view_total_scores(self):
        """ 查看总分窗口 """
        total_window = tk.Toplevel(self.root)
        total_window.title("总分")

        total_label = tk.Label(total_window, text="所有运动员总分:")
        total_label.pack(padx=10, pady=5)
        total_score = sum(athlete.score * (2 if athlete.is_record else 1) for athlete in self.scores)
        all_scores_label = tk.Label(total_window, text=f"总分: {total_score}")
        all_scores_label.pack(padx=10, pady=5)

        # 计算平均分、最高分、最低分
        if self.scores:
            average_score = total_score / len(self.scores)
            highest_score = max(athlete.score for athlete in self.scores)
            lowest_score = min(athlete.score for athlete in self.scores)
        else:
            average_score = highest_score = lowest_score = 0

        stats_label = tk.Label(total_window, text=f"平均分: {average_score:.2f}, 最高分: {highest_score}, 最低分: {lowest_score}")
        stats_label.pack(padx=10, pady=5)

        # 各分组的总分
        group_scores = {}
        for athlete in self.scores:
            group = athlete.group
            group_score = athlete.score * (2 if athlete.is_record else 1)
            group_scores[group] = group_scores.get(group, 0) + group_score
        
        # 显示各组的总分
        group_total_label = tk.Label(total_window, text="各分组总分:")
        group_total_label.pack(padx=10, pady=5)

        for group, group_total in group_scores.items():
            group_score_label = tk.Label(total_window, text=f"{group}: {group_total}")
            group_score_label.pack(padx=10, pady=5)

    def export_to_csv(self):
        """ 弹出文件对话框选择保存路径并导出 CSV """
        filename = filedialog.asksaveasfilename(defaultextension=".csv", filetypes=[("CSV files", "*.csv")])
        if filename:
            with open(filename, mode='w', newline='', encoding='utf-8') as file:
                writer = csv.writer(file)
                writer.writerow(["分组", "姓名", "名次", "分数", "破纪录"])
                for athlete in self.scores:
                    writer.writerow([athlete.group, athlete.name, athlete.rank, athlete.score, athlete.is_record])
            messagebox.showinfo("成功", f"数据已导出到 {filename}")

    def delete_selected(self):
        selected_item = self.tree.selection()
        if selected_item:
            for item in selected_item:
                index = self.tree.index(item)
                self.tree.delete(item)
                # 从列表中删除相应的运动员信息
                del self.scores[index]
                self.update_displayed_athletes()  # 更新显示
        else:
            messagebox.showwarning("选择错误", "请先选择一行!")

    def open_settings(self):
        """ 打开设置分数的窗口 """
        settings_window = tk.Toplevel(self.root)
        settings_window.title("设置分数")

        self.rank_income_vars = {}
        for rank in range(1, 9):
            tk.Label(settings_window, text=f"第{rank}名分数:").grid(row=rank-1, column=0, padx=5, pady=5)
            var = tk.StringVar(value=self.rank_to_score.get(rank, 0))
            self.rank_income_vars[rank] = var
            tk.Entry(settings_window, textvariable=var).grid(row=rank-1, column=1, padx=5, pady=5)

        tk.Button(settings_window, text="确认", command=self.save_settings).grid(row=8, columnspan=2, pady=10)

    def save_settings(self):
        for rank, var in self.rank_income_vars.items():
            try:
                score = int(var.get())
                self.rank_to_score[rank] = score
            except ValueError:
                messagebox.showwarning("输入错误", f"名次 {rank} 的分数无效,请输入数字!")
                return

        for index, athlete in enumerate(self.scores):
            # 更新分数
            if athlete.rank in self.rank_to_score:
                score = self.rank_to_score[athlete.rank]
                athlete.score = score  # 更新分数
                if index < len(self.tree.get_children()):  # 确保索引有效
                    self.tree.item(self.tree.get_children()[index], values=(athlete.group, athlete.name, athlete.rank, score, athlete.is_record))

        messagebox.showinfo("成功", "分数设置已更新!")

    def toggle_record(self):
        selected_item = self.tree.selection()
        if selected_item:
            item = selected_item[0]
            index = self.tree.index(item)
            athlete = self.scores[index]  # 获取运动员信息
            
            athlete.is_record = not athlete.is_record  # 切换破纪录状态

            # 更新分数
            if athlete.is_record:
                athlete.score *= 2
            else:
                athlete.score //= 2

            # 更新树形控件
            self.tree.item(item, values=(athlete.group, athlete.name, athlete.rank, athlete.score, "✔" if athlete.is_record else "✖"))

    def show_popup(self, event):
        try:
            selected = self.tree.identify_row(event.y)
            if selected:
                self.tree.selection_set(selected)
                self.popup_menu.post(event.x_root, event.y_root)
        except Exception as e:
            print(f"Error showing popup menu: {e}")

    def open_group_management(self):
        """ 打开分组管理窗口 """
        group_window = tk.Toplevel(self.root)
        group_window.title("管理分组")
        
        tk.Label(group_window, text="自定义分组:").grid(row=0, column=0, padx=10, pady=5)
        custom_group_entry = tk.Entry(group_window)
        custom_group_entry.grid(row=0, column=1, padx=10, pady=5)

        tk.Button(group_window, text="添加分组", command=lambda: self.add_custom_group(custom_group_entry.get())).grid(row=0, column=2, padx=10, pady=5)

        tk.Label(group_window, text="当前分组:").grid(row=1, column=0, padx=10, pady=5)
        current_groups_var = StringVar(value=", ".join(sorted(self.available_groups)))
        tk.Entry(group_window, textvariable=current_groups_var, state='readonly').grid(row=1, column=1, padx=10, pady=5)

        tk.Label(group_window, text="删除分组:").grid(row=2, column=0, padx=10, pady=5)
        delete_group_entry = tk.Entry(group_window)
        delete_group_entry.grid(row=2, column=1, padx=10, pady=5)

        tk.Button(group_window, text="删除分组", command=lambda: self.delete_custom_group(delete_group_entry.get())).grid(row=2, column=2, padx=10, pady=5)

    def add_custom_group(self, group_name):
        """ 添加自定义分组 """
        if group_name and group_name not in self.available_groups:
            self.available_groups.add(group_name)
            self.setup_group_selection()  # 更新分组选择菜单
            messagebox.showinfo("成功", f"已添加自定义分组: {group_name}")
        else:
            messagebox.showwarning("输入错误", "分组名称不能为空或已存在!")

    def delete_custom_group(self, group_name):
        """ 删除自定义分组 """
        if group_name in self.available_groups:
            self.available_groups.remove(group_name)
            self.setup_group_selection()  # 更新分组选择菜单
            messagebox.showinfo("成功", f"已删除分组: {group_name}")
        else:
            messagebox.showwarning("输入错误", "该分组不存在!")

    def show_help(self):
        help_message = (
            "本软件用于运动会计分管理...\n"
            "使用说明:\n"
            "1. 请依次输入运动员信息,选择分组或自定义分组。\n"
            "2. 点击“添加运动员”来记录。\n"
            "3. 点击“查看总分”可以查看所有运动员及各分组的总分。\n"
            "4. 右键点击运动员可以切换破纪录状态。\n"
            "5. 点击“导出数据”将运动员信息导出为CSV文件。"
        )
        messagebox.showinfo("帮助", help_message)

if __name__ == "__main__":
    root = tk.Tk()
    app = ScoreApp(root)
    root.mainloop()

#这个示例代码用了tkinter库来做GUI,其中我采用的的是Tree组件使界面有一个类似于电子表格的管理方式
#scv库的作用是可以让统计的数据导出
#其中的tkinter库和scv库都是自带的
#现在看一下运行后的成果
#这里选用如果破纪录是翻倍分数

源码地址:https://download.csdn.net/download/HYP_Coder/90001597?spm=1001.2014.3001.5503

B站视频:嗯?别进来!_哔哩哔哩_bilibili

标签:group,计分,Python,athlete,window,管理软件,score,tk,self
From: https://blog.csdn.net/HYP_Coder/article/details/143868152

相关文章

  • Python 时间模块(time,datetime)
    在Python中,time模块和datetime模块都与时间处理相关,但它们有着不同的特点和用途,以下为你详细介绍:一.time模块概述:time模块提供了各种与时间相关的函数,它主要围绕着时间戳(从1970年1月1日00:00:00UTC到某个时刻所经过的秒数)来进行操作,常用于获取当前时间、对时间进......
  • 解释爬虫的基本概念,以及它的作用,并讲解如何使用 Python 实现网络爬虫。
    爬虫是一种自动化程序,用于从互联网上收集数据。它通过模拟人类访问网页的行为,自动发送HTTP请求,获取网页内容,并抽取所需的数据。爬虫的作用非常广泛。它可以用于搜索引擎的网页索引,获取新闻、博客等网页内容,进行数据挖掘和分析,监测网站的变化等。Python是一种常用的编程语言......
  • Zmap+python脚本+burp实现自动化Fuzzing测试
    声明学习视频来自B站UP主泷羽sec,如涉及侵权马上删除文章。笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负。✍......
  • 计算机毕设项目源代码 python基于python的旅游可视化系统
    标题: python基于python的旅游可视化系统设计一个基于Python的旅游可视化系统,可以帮助用户更好地规划旅行路线,了解目的地的详细信息,并提供丰富的互动功能。以下是一个典型的旅游可视化系统的主要功能模块:1.系统概述•目标:为用户提供一个直观、易用的旅游信息平台,帮助用户......
  • 计算机毕设源码 python-基于flask在线考试系统
    标题:python-基于flask在线考试系统设计一个基于Flask框架的在线考试系统,需要考虑考生、教师和管理员的不同需求,确保系统的易用性、公平性和安全性。以下是一个典型的在线考试系统的主要功能模块:1.用户注册与登录•注册:用户可以通过手机号码、邮箱或社交账号注册。•登录:用......
  • 计算机毕设设计项目 python基于flask框架的车联网数据库系统的构建
    标题:python基于flask框架的车联网数据库系设计一个基于Flask框架的车联网数据库系统,需要考虑车辆数据的收集、存储、分析和管理,确保系统的高效性、可靠性和扩展性。以下是一个典型的车联网数据库系统的主要功能模块:1.用户注册与登录•注册:用户可以通过手机号码、邮箱或社......
  • 计算机毕设设计项目 python基于flask的校园失物招领系统设计与实现
    标题: python基于flask的校园失物招领系统设计设计一个基于Flask框架的校园失物招领系统,需要考虑学生、教师和其他校园成员的需求,确保系统的易用性、高效性和安全性。以下是一个典型的校园失物招领系统的主要功能模块:1.用户注册与登录•注册:用户可以通过手机号码、学号/工......
  • conda linux 管理python 环境
    一、conda是什么?Conda是一个开源的软件包管理系统和环境管理系统,用于在不同的操作系统上安装、运行和管理多个软件包和环境。它可以用于管理Python软件包和其他编程语言的软件包,具有自动解决依赖关系、创建独立环境、轻松切换环境等功能。Conda提供了一个命令行界面和一个图形界......
  • python中的模块、库、包有什么区别?
    Python用得多了,少不了和这几个概念打交道,但别说初学者了,很多老程序员一开始也迷糊。这不,有不少人都是“模块”、“库”随便混着叫,甚至把“包”也拉下水。今天咱们就来掰扯清楚这三者的区别和用法。模块:文件级别的组织首先,Python的“模块”指的是一个文件,也就是.py结尾的......
  • 02-python进阶笔记
    python进阶笔记面向对象思想:找人帮我做事面向过程:一步一步亲力亲为面向对象三大特征:封装性,继承性,多态性类和对象函数是一个封装类也是一个更大封装类:属性:事物的描述信息行为:事物的行动能力类-:具有单个或者多个属性或者方法的集合体的统称,是抽象的.不能......