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