C++ Qt框架开发 | 基于Qt框架开发实时成绩显示排序系统(1)

目标:旨在开发一个用户友好的软件工具,用于协助用户基于输入对象的成绩数据进行排序。该工具的特色在于,新输入的数据将以红色高亮显示,从而直观地展现出排序过程中数据变化的每一个步骤。

结果展示:

        本程序是一个基于Qt框架开发的用户友好型软件工具,专为管理和展示运动员成绩信息而设计。 该程序的亮点在于其直观的数据展示方式。新输入或更新的运动员数据会以红色高亮显示,使用户能够清晰地追踪每次操作后数据的变化。 通过精心设计的GUI,该工具提供了清晰、易于导航的用户界面,包括用于数据展示的表格视图、用于输入和编辑运动员信息的表单,以及一系列操作按钮,如排序、添加新运动员、编辑选定运动员和删除运动员等。整个应用旨在为教练、体育分析师或团队管理者等用户提供一个高效、直观的运动员管理和分析平台。 

        话不多说直接上代码!


一、算法实现 (此步请直接跳过)

关于如何使用VSCode实现C++编程给大家推荐这个博文,写的很好:vscode配置C/C++环境(超详细保姆级教学)-CSDN博客

1)先定义一个对象,包含姓名、年龄、身高和成绩等属性。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class Athlete {
public:
    string name;
    int age;
    float height;
    float score;

    Athlete(string n, int a, float h, float s) : name(n), age(a), height(h), score(s) {}

    bool operator < (const Athlete& athlete) const {
        return score < athlete.score;
    }
};

2)若数据集小直接插入排序最快,数据集大快速排序比较好,因此选取了这两种方法,可根据数据集大小自行选择。

// 直接插入排序
void insertionSort(vector<Athlete>& arr) {
    for (int i = 1; i < arr.size(); i++) {
        Athlete key = arr[i];
        int j = i - 1;
        while (j >= 0 && arr[j].score > key.score) {
            arr[j + 1] = arr[j];
            j = j - 1;
        }
        arr[j + 1] = key;
    }
}


// 快速排序
int partition(vector<Athlete>& arr, int low, int high) {
    float pivot = arr[high].score;
    int i = (low - 1);
    for (int j = low; j <= high - 1; j++) {
        if (arr[j].score < pivot) {
            i++;
            swap(arr[i], arr[j]);
        }
    }
    swap(arr[i + 1], arr[high]);
    return (i + 1);
}

void quickSort(vector<Athlete>& arr, int low, int high) {
    if (low < high) {
        int pi = partition(arr, low, high);
        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    }
}

算法相关的内容大概就这些,现在开始使用Qt实现可视化界面。


二、Qt 实现(我使用的是Qt 5.14.2)

Qt下载:Index of /archive/qt
关于Qt的学习分享一个up主的课程:1.4 Qt的安装_哔哩哔哩_bilibili

程序结构文件:

1)athlete.h
#ifndef ATHLETE_H
#define ATHLETE_H

#include <string>
using std::string;

class Athlete {
public:
    string name;
    float scores[6] = {0}; // 假设有6轮成绩
    float totalScore = 0; // 总成绩

    // 更新指定轮次的成绩并重新计算总成绩
    void updateScore(int round, float score) {
        if (round >= 1 && round <= 6) { // 确保轮次有效
            scores[round - 1] = score; // 更新成绩,轮次从1开始,数组索引从0开始
            calculateTotalScore(); // 重新计算总成绩
        }
    }

    // 计算总成绩
    void calculateTotalScore() {
        totalScore = 0;
        for (int i = 0; i < 6; ++i) {
            totalScore += scores[i];
        }
    }
};

#endif // ATHLETE_H
2)athletemodel.h
#ifndef ATHLETEMODEL_H
#define ATHLETEMODEL_H

#include <QStandardItemModel>
#include "athlete.h" // 确保这里正确包含了你的Athlete类定义

class AthleteModel : public QStandardItemModel {
    Q_OBJECT

public:
    explicit AthleteModel(QObject *parent = nullptr);

    // 添加或更新运动员的成绩,根据需要创建新运动员
    void updateAthleteScore(const std::string& name, int round, float score);

private:
    // 辅助函数,根据运动员名字查找对应的行。如果找不到,返回-1
    int findRowByName(const std::string& name);
};

#endif // ATHLETEMODEL_H
3)mainwindow.h
//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <vector>
#include "athlete.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void displayAthleteInfo(const std::vector<Athlete>& athletes);
private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
4)athletemodel.cpp
#include "athletemodel.h"
#include <QStandardItem>
#include <QBrush> // 用于设置颜色

AthleteModel::AthleteModel(QObject *parent) : QStandardItemModel(parent) {
    setHorizontalHeaderLabels({"Name", "1", "2", "3", "4", "5", "6", "Total"});
}

void AthleteModel::updateAthleteScore(const std::string& name, int round, float score) {
    int row = findRowByName(name);
    QBrush redBrush(Qt::red);
    QBrush defaultBrush(Qt::black); // 默认颜色
    int newRow = -1; // 新行索引

    // 首先,将所有行的颜色设置回默认颜色
    for (int r = 0; r < rowCount(); ++r) {
        for (int c = 0; c < columnCount(); ++c) {
            auto item = this->item(r, c);
            item->setForeground(defaultBrush);
        }
    }
    if (row == -1) {
        // 运动员不存在,创建新运动员
        QList<QStandardItem*> items;
        items << new QStandardItem(QString::fromStdString(name));

        for (int i = 1; i <= 6; ++i) {
            items << new QStandardItem(QString::number(i == round ? score : 0.0f)); // 除了当前轮次外其他成绩初始化为0
        }
        items << new QStandardItem(QString::number(score)); // 总成绩初始化为当前轮次成绩
        newRow = rowCount(); // 新添加的行是当前行数(因为还没有实际添加)
        appendRow(items);
    } else {
        // 运动员已存在,更新成绩
        auto scoreItem = item(row, round);
        float oldScore = scoreItem->text().toFloat();
        scoreItem->setText(QString::number(score));

        // 更新总成绩
        auto totalItem = item(row, 7);
        float totalScore = totalItem->text().toFloat() - oldScore + score;
        totalItem->setText(QString::number(totalScore));
        newRow = row; // 更新的行就是找到的行
        if (newRow != -1) {
                for (int column = 0; column < columnCount(); ++column) {
                    auto item = this->item(newRow, column);
                    item->setForeground(redBrush);
          }
       }
    }
}

int AthleteModel::findRowByName(const std::string& name) {
    for (int row = 0; row < rowCount(); ++row) {
        if (item(row, 0)->text() == QString::fromStdString(name)) {
            return row;
        }
    }
    return -1; // 运动员不存在
}
5)main.cpp
#include "mainwindow.h"
#include "athlete.h"
#include <QApplication>


int main(int argc, char *argv[])
{
    // 应用程序类,在一个qt应用程序中,该对象只有一个
    QApplication a(argc, argv);
    // 窗口对象
    MainWindow w;
    // 显示函数
    w.show();
    // 阻塞函数,程序事件循环
    return a.exec();
}
6)mainwindow.cpp
//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "athletemodel.h"
#include <QSortFilterProxyModel>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow) {
    ui->setupUi(this);

    // 设置窗口标题
    setWindowTitle("运动员成绩显示系统");

    // 设置窗口图标
    setWindowIcon(QIcon("E:\\CoachManagementSystem\\shooting coaches and athletes.png"));

    auto model = new AthleteModel(this);
    auto proxyModel = new QSortFilterProxyModel(this);
    proxyModel->setSourceModel(model);
    ui->tableView->setModel(proxyModel);
    ui->comboBox->addItems({"1", "2", "3", "4", "5", "6"});

    connect(ui->pushButton, &QPushButton::clicked, this, [this, model, proxyModel]() {
        QString name = ui->textEdit_2->toPlainText().trimmed();
        float score = static_cast<float>(ui->doubleSpinBox->value());
        int round = ui->comboBox->currentIndex() + 1; // +1 because rounds are 1-based

        if (name.isEmpty()) {
                // Handle empty name input appropriately
                return;
        }

        // 更新或添加运动员成绩
        model->updateAthleteScore(name.toStdString(), round, score); // 此方法需要在model中实现

        // 重新排序,这里假设proxyModel已经设置为根据总成绩降序排序

        proxyModel->sort(7, Qt::DescendingOrder); // 假设总成绩在第8列(列索引为7)
        ui->tableView->reset();

    });
}

MainWindow::~MainWindow() {
    delete ui;
}
7)mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>1061</width>
    <height>589</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QPushButton" name="pushButton">
    <property name="geometry">
     <rect>
      <x>470</x>
      <y>500</y>
      <width>91</width>
      <height>31</height>
     </rect>
    </property>
    <property name="text">
     <string>更新</string>
    </property>
   </widget>
   <widget class="QDoubleSpinBox" name="doubleSpinBox">
    <property name="geometry">
     <rect>
      <x>350</x>
      <y>500</y>
      <width>91</width>
      <height>31</height>
     </rect>
    </property>
    <property name="maximum">
     <double>999.990000000000009</double>
    </property>
   </widget>
   <widget class="QLabel" name="label">
    <property name="geometry">
     <rect>
      <x>220</x>
      <y>480</y>
      <width>31</width>
      <height>16</height>
     </rect>
    </property>
    <property name="text">
     <string>姓名</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_2">
    <property name="geometry">
     <rect>
      <x>380</x>
      <y>480</y>
      <width>31</width>
      <height>16</height>
     </rect>
    </property>
    <property name="text">
     <string>成绩</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_3">
    <property name="geometry">
     <rect>
      <x>510</x>
      <y>20</y>
      <width>91</width>
      <height>16</height>
     </rect>
    </property>
    <property name="text">
     <string>实时成绩展示</string>
    </property>
   </widget>
   <widget class="QTextEdit" name="textEdit_2">
    <property name="geometry">
     <rect>
      <x>150</x>
      <y>500</y>
      <width>171</width>
      <height>31</height>
     </rect>
    </property>
   </widget>
   <widget class="QComboBox" name="comboBox">
    <property name="geometry">
     <rect>
      <x>30</x>
      <y>500</y>
      <width>101</width>
      <height>31</height>
     </rect>
    </property>
   </widget>
   <widget class="QTableView" name="tableView">
    <property name="geometry">
     <rect>
      <x>15</x>
      <y>41</y>
      <width>1031</width>
      <height>421</height>
     </rect>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>1061</width>
     <height>26</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

对系统进一步优化,显示运动员成绩折线图,参考我下一篇博文

C++学习笔记 | 基于Qt框架开发实时成绩显示排序系统2——折线图显示-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/385916.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在Ubuntu22.04上部署FoooCUS2.1

Fooocus 是一款基于 Gradio的图像生成软件&#xff0c;Fooocus 是对 Stable Diffusion 和 Midjourney 设计的重新思考&#xff1a; 1、从 Stable Diffusion 学习&#xff0c;该软件是离线的、开源的和免费的。 2、从 Midjourney 中学到&#xff0c;不需要手动调整&#xff0c;…

嵌入式Qt 计算器界面设计代码重构

一.计算器界面设计代码重构 计算器界面设计&#xff1a;嵌入式Qt 计算器界面设计-CSDN博客 重构的概念&#xff1a; 代码实现与代码重构的不同&#xff1a; 软件开发过程&#xff1a; 什么样的代码需要重构&#xff1a; 计算器界面代码重构的框架设计&#xff1a; 实验&#…

理解JAVA命名和目录接口(JNDI)

理解JAVA命名和目录接口(JNDI) 考虑访问网站的场景,Web用户要求记住四字节的IP地址而不是有意义的名称。例如,假设Web用户用123.23.3.123而不是hotmail.com访问hotmail网站。在这种情形下,Web用户难以记住不同的IP地址来访问不同的网站。因此,要使其变得对Web用户简单方…

Unity下使用Sqlite

sqlite和access类似是文件形式的数据库&#xff0c;不需要安装任何服务&#xff0c;可以存储数据&#xff0c;使用起来还是挺方便的。 首先需要安装DLL 需要的DLL 我们找到下面两个文件放入Plugins目录 Mono.Data.Sqlite.dll System.Data.dll DLL文件位于Unity的安装目录下的…

分布式文件系统 SpringBoot+FastDFS+Vue.js

分布式文件系统 SpringBootFastDFSVue.js 一、分布式文件系统1.1.文件系统1.2.什么是分布式文件系统1.3.分布式文件系统的出现1.3.主流的分布式文件系统1.4.分布式文件服务提供商1.4.1.阿里OSS1.4.2.七牛云存储1.4.3.百度云存储 二、fastDFS2.1.fastDSF介绍2.2.为什么要使用fas…

第4讲 小程序首页实现

首页 create.vue <template><view class"vote_type"><view class"vote_tip_wrap"><text class"type_tip">请选择投票类型</text><!-- <text class"share">&#xe739;分享给朋友</text&g…

如何在C# Windows Forms应用程序中实现控件之间的连接线

帮我实现绘图工具多个控件连接线&#xff0c;请用c#代码实现 实现绘图工具中多个控件之间的连接线功能&#xff0c;可以通过以下几个步骤来进行&#xff1a; 定义连接线的数据模型&#xff1a;首先需要定义一个模型来表示连接线&#xff0c;这个模型应该包含起点和终点的坐标。…

JavaScript中有哪些不同的数据类型

在 JavaScript 中&#xff0c;数据类型是一种用来表示数据的分类&#xff0c;它决定了我们可以对这个数据类型执行哪些操作。在 JavaScript 中有以下几种不同的数据类型&#xff1a; 基本数据类型 字符串 (String)&#xff1a;表示一组字符&#xff0c;可以使用引号&#xff08…

Pytorch的可视化

1 使用 wandb进行可视化训练过程 本文章将从wandb的安装、wandb的使用、demo的演示进行讲解。 1.1 如何安装wandb&#xff1f; wandb的安装比较简单&#xff0c;在终端中执行如下的命令即可&#xff1a; pip install wandb在安装完成之后&#xff0c;我们需要&#xff0c;去…

华为机考入门python3--(13)牛客13-句子逆序

分类&#xff1a;列表 知识点&#xff1a; 列表逆序&#xff08;和字符串逆序是一样的&#xff09; my_list[::-1] 题目来自【牛客】 def reverse_sentence(sentence): # 将输入的句子分割words sentence.split() # 将单词逆序排列 words words[::-1] # 将单词用空…

DarkSide针对VMware EXSI系统进行加密

前言 最近黑客组织利用DarkSide勒索病毒对Colonial Pipeline 发起勒索攻击&#xff0c;国内外各大安全厂商和安全媒体也都有相关报道&#xff0c;DarkSide勒索软件是从2020年8月出现&#xff0c;并以(RAAS)勒索即服务的商业模式进行运作&#xff0c;此勒索病毒不仅可以部署基于…

【Chrono Engine学习总结】5-sensor-5.1-sensor基础并创建一个lidar

由于Chrono的官方教程在一些细节方面解释的并不清楚&#xff0c;自己做了一些尝试&#xff0c;做学习总结。 1、Sensor模块 Sensor模块是附加模块&#xff0c;需要单独安装。参考&#xff1a;【Chrono Engine学习总结】1-安装配置与程序运行 Sensor Module Tutorial Sensor …

MySQL数据库⑧_索引(概念+理解+操作)

目录 1. 索引的概念和价值 1.1 索引的概念 1.2 索引的价值 2. 磁盘的概念 2.1 磁盘的结构 2.2 操作系统与磁盘交互的基本单位 2.3 MySQL与磁盘交互的基本单位 3. 索引的理解 3.1 主键索引现象和推导 3.2 索引采用的数据结构&#xff1a;B树 3.3 聚簇索引和非聚簇索引…

Java并发基础:DelayQueue全面解析!

内容概要 DelayQueue类专为处理延迟任务设计&#xff0c;它允许开发者将任务与指定的延迟时间关联&#xff0c;并在任务到期时自动处理&#xff0c;从而避免了不必要的轮询和资源浪费&#xff0c;此外&#xff0c;DelayQueue内部基于优先队列实现&#xff0c;确保最先到期的任…

蓝桥杯每日一题------背包问题(三)

前言 之前求的是在特点情况下选择一些物品让其价值最大&#xff0c;这里求的是方案数以及具体的方案。 背包问题求方案数 既然要求方案数&#xff0c;那么就需要一个新的数组来记录方案数。动态规划步骤如下&#xff0c; 定义dp数组 第一步&#xff1a;缩小规模。考虑n个物品…

ubuntu22.04@laptop OpenCV Get Started: 007_color_spaces

ubuntu22.04laptop OpenCV Get Started: 007_color_spaces 1. 源由2. 颜色空间2.1 RGB颜色空间2.2 LAB颜色空间2.3 YCrCb颜色空间2.4 HSV颜色空间 3 代码工程结构3.1 C应用Demo3.2 Python应用Demo 4. 重点分析4.1 interactive_color_detect4.2 interactive_color_segment4.3 da…

【MySQL】学习约束和使用图形化界面创建表

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-iqtbME2KmWpQFQSt {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

调用讯飞火星AI大模型WebAPI

调用讯飞火星AI大模型 记录一次调用讯飞AI大模型的过程 官方文档 首先&#xff0c;去官网申请资格&#xff0c;获得必要秘钥等 再编写url&#xff0c;该url存在编码要求&#xff0c;具体看官网url编写 具体代码如下&#xff1a; getWebsocketUrl() {return new Promise((resol…

Peter算法小课堂—区间模型

Peter Pan来啦…… 最大不重叠区间数 二话不说&#xff0c;先来一道题 大家想想怎么贪心&#xff1f;我们可以将每一个美食摊位抽象成一个区间&#xff0c;区间左端点为开始排队时间&#xff0c;右端点为结束排队时间。其中&#xff0c;时间信息可以用数轴表示。 额……我们…

golang集成sentry: go-redis

网上没有找到go-redis集成sentry的库&#xff0c; 所以我简单实现了一个 代码&#xff1a; https://github.com/Shujie-Tan/go-redis-sentry 使用方法&#xff1a; import (redis_sentry "github.com/Shujie-Tan/go-redis-sentry" ) rdb : redis.NewClient(&re…