学习点
Qlabel 每五个一换行 并、号分割
QString MainWindow::formatHobbies(const std::set<QString>& hobbies) {
QString formattedHobbies;
int count = 0;
for (const QString& hobby : hobbies) {
if (count > 0 && count % 5 == 0)
formattedHobbies += "\n"; // 每 5 个换行
formattedHobbies += hobby + "、";
++count;
}
// 去掉最后一个 "、"
if (!formattedHobbies.isEmpty())
formattedHobbies.chop(1);
return formattedHobbies;
}
效果图展示
Qlabel 每五个一换行 对齐排列
使用 QGridLayout 来排列爱好标签。
每行最多显示 5 个爱好,如果超过 5 个则换行。
使用 QLabel 来显示每个爱好,确保这些标签有一致的大小,并进行对齐
QGridLayout* hobbiesLayout;
//添加到对应布局
QWidget* rightPanel = new QWidget();
QVBoxLayout* rightLayout = new QVBoxLayout(rightPanel);
studentInfoLabel = new QLabel();
rightLayout->addWidget(studentInfoLabel);
// Create a layout for hobbies
hobbiesLayout = new QGridLayout();
hobbiesWidget = new QWidget();
hobbiesWidget->setLayout(hobbiesLayout);
rightLayout->addWidget(hobbiesWidget);
//具体实现
void MainWindow::updateHobbiesLayout(const std::set<QString>& hobbies)
{
// Clear the previous hobbies
QLayoutItem* item;
while ((item = hobbiesLayout->takeAt(0)) != nullptr) {
delete item->widget();
delete item;
}
// Add the new hobbies
int row = 0, col = 0;
for (const QString& hobby : hobbies) {
QLabel* hobbyLabel = new QLabel(hobby);
hobbyLabel->setAlignment(Qt::AlignCenter);
hobbyLabel->setFixedSize(100, 30); // Fix label size
hobbiesLayout->addWidget(hobbyLabel, row, col);
++col;
if (col == 5) {
col = 0;
++row;
}
}
}
添加滑动条
// Right: Scroll area for hobbies and other widgets
hobbiesWidget->setLayout(new QGridLayout());
hobbiesScrollArea->setWidget(hobbiesWidget);
hobbiesScrollArea->setWidgetResizable(true);
hobbiesScrollArea->setMaximumHeight(40); // Minimum height
hobbiesScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
hobbiesScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
rightLayout->addWidget(hobbiesScrollArea);
void MainWindow::updateHobbiesLayout(const std::set<QString>& hobbies) {
QGridLayout* layout = qobject_cast<QGridLayout*>(hobbiesWidget->layout());
if (!layout)
return;
// Clear existing layout items
while (QLayoutItem* item = layout->takeAt(0)) {
delete item->widget();
delete item;
}
// Add hobbies to grid layout
int row = 0, col = 0;
for (const auto& hobby : hobbies) {
QLabel* hobbyLabel = new QLabel(hobby);
layout->addWidget(hobbyLabel, row, col);
if (++col >= 5) {
col = 0;
++row;
}
}
hobbiesWidget->adjustSize();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTreeWidget>
#include <QStackedWidget>
#include <QTableWidget>
#include <QLabel>
#include <QTabWidget>
#include <vector>
#include <set>
struct Student {
QString id;
QString name;
QString className;
int chinese;
int math;
int english;
std::set<QString> hobbies;
std::set<QString> honors;
};
struct Teacher {
QString id;
QString name;
std::set<QString> subjects; // 任课科目
std::set<QString> classes; // 所教班级
};
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
private:
void setupUI();
void loadStudentData();
void loadTeacherData();
void displayStudentDetails(const Student &student);
void displayTeacherDetails(const Teacher &teacher);
QStringList setToQStringList(const std::set<QString> &set);
// 左侧控件
QTabWidget *tabWidget;
QTreeWidget *studentTree;
QTreeWidget *teacherTree;
// 右侧控件
QStackedWidget *stackedWidget;
QWidget *studentPage;
QWidget *teacherPage;
// 学生界面
QLabel *studentInfoLabel;
QTableWidget *studentTable;
// 教师界面
QLabel *teacherInfoLabel;
QTableWidget *teacherTable;
// 数据
std::vector<Student> students;
std::vector<Teacher> teachers;
private slots:
void onTabChanged(int index);
void onTreeItemClicked(QTreeWidgetItem *item, int column);
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QStringList>
#include <cstdlib>
#include <ctime>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
setupUI();
loadStudentData();
loadTeacherData();
}
void MainWindow::setupUI() {
// 左侧 Tab 页
tabWidget = new QTabWidget(this);
studentTree = new QTreeWidget(tabWidget);
teacherTree = new QTreeWidget(tabWidget);
studentTree->setHeaderLabel("学生 ID");
teacherTree->setHeaderLabel("教师 ID");
tabWidget->addTab(studentTree, "学生信息");
tabWidget->addTab(teacherTree, "教师信息");
connect(tabWidget, &QTabWidget::currentChanged, this, &MainWindow::onTabChanged);
connect(studentTree, &QTreeWidget::itemClicked, this, &MainWindow::onTreeItemClicked);
connect(teacherTree, &QTreeWidget::itemClicked, this, &MainWindow::onTreeItemClicked);
// 右侧 StackedWidget
stackedWidget = new QStackedWidget(this);
studentPage = new QWidget(stackedWidget);
teacherPage = new QWidget(stackedWidget);
stackedWidget->addWidget(studentPage);
stackedWidget->addWidget(teacherPage);
// 学生界面布局
QVBoxLayout *studentLayout = new QVBoxLayout(studentPage);
studentInfoLabel = new QLabel("学生详细信息", studentPage);
studentTable = new QTableWidget(studentPage);
studentTable->setColumnCount(3);
studentTable->setHorizontalHeaderLabels({"语文", "数学", "英语"});
studentTable->horizontalHeader()->setStretchLastSection(true);
studentTable->verticalHeader()->setVisible(false);
studentLayout->addWidget(studentInfoLabel);
studentLayout->addWidget(studentTable);
// 教师界面布局
QVBoxLayout *teacherLayout = new QVBoxLayout(teacherPage);
teacherInfoLabel = new QLabel("教师详细信息", teacherPage);
teacherTable = new QTableWidget(teacherPage);
teacherTable->setColumnCount(2);
teacherTable->setHorizontalHeaderLabels({"班级", "学生数量"});
teacherTable->horizontalHeader()->setStretchLastSection(true);
teacherTable->verticalHeader()->setVisible(false);
teacherLayout->addWidget(teacherInfoLabel);
teacherLayout->addWidget(teacherTable);
// 主布局
QHBoxLayout *mainLayout = new QHBoxLayout();
mainLayout->addWidget(tabWidget, 1);
mainLayout->addWidget(stackedWidget, 3);
QWidget *central = new QWidget(this);
central->setLayout(mainLayout);
setCentralWidget(central);
}
void MainWindow::loadStudentData() {
srand(static_cast<unsigned>(time(nullptr)));
for (int i = 1; i <= 30; ++i) {
Student student;
student.id = QString("ID%1").arg(i, 2, 10, QChar('0'));
student.name = QString("学生%1").arg(i);
student.className = QString("高三%1班").arg(i % 5 + 1);
student.chinese = rand() % 40 + 60;
student.math = rand() % 40 + 60;
student.english = rand() % 40 + 60;
student.hobbies = {"篮球", "足球", "画画", "写作", "音乐"};
student.honors = {"优秀学生", "三好学生", "数学竞赛一等奖", "文艺活动积极分子"};
students.push_back(student);
QTreeWidgetItem *item = new QTreeWidgetItem(studentTree);
item->setText(0, student.id);
}
}
void MainWindow::loadTeacherData() {
for (int i = 1; i <= 10; ++i) {
Teacher teacher;
teacher.id = QString("T%1").arg(i, 2, 10, QChar('0'));
teacher.name = QString("教师%1").arg(i);
teacher.subjects = {"语文", "数学", "英语"};
teacher.classes = {"高一1班", "高二2班", "高三3班"};
teachers.push_back(teacher);
QTreeWidgetItem *item = new QTreeWidgetItem(teacherTree);
item->setText(0, teacher.id);
}
}
void MainWindow::onTabChanged(int index) {
if (index == 0) {
stackedWidget->setCurrentWidget(studentPage);
} else if (index == 1) {
stackedWidget->setCurrentWidget(teacherPage);
}
}
void MainWindow::onTreeItemClicked(QTreeWidgetItem *item, int column) {
QString id = item->text(column);
if (tabWidget->currentIndex() == 0) {
for (const auto &student : students) {
if (student.id == id) {
displayStudentDetails(student);
break;
}
}
} else if (tabWidget->currentIndex() == 1) {
for (const auto &teacher : teachers) {
if (teacher.id == id) {
displayTeacherDetails(teacher);
break;
}
}
}
}
void MainWindow::displayStudentDetails(const Student &student) {
//QString hobbies = QStringList(student.hobbies.begin(), student.hobbies.end()).join("、");
QString hobbies = setToQStringList(student.hobbies).join("、");
studentInfoLabel->setText(
QString("学号: %1\n姓名: %2\n班级: %3\n爱好: %4")
.arg(student.id)
.arg(student.name)
.arg(student.className)
.arg(hobbies)
);
studentTable->setRowCount(1);
studentTable->setItem(0, 0, new QTableWidgetItem(QString::number(student.chinese)));
studentTable->setItem(0, 1, new QTableWidgetItem(QString::number(student.math)));
studentTable->setItem(0, 2, new QTableWidgetItem(QString::number(student.english)));
}
void MainWindow::displayTeacherDetails(const Teacher &teacher) {
QString subjects = setToQStringList(teacher.subjects).join("、");
teacherInfoLabel->setText(
QString("工号: %1\n姓名: %2\n任课科目: %3")
.arg(teacher.id)
.arg(teacher.name)
.arg(subjects)
);
teacherTable->setRowCount(teacher.classes.size());
int row = 0;
for (const auto &cls : teacher.classes) {
teacherTable->setItem(row, 0, new QTableWidgetItem(cls));
teacherTable->setItem(row, 1, new QTableWidgetItem(QString::number(rand() % 50 + 10)));
++row;
}
}
QStringList MainWindow::setToQStringList(const std::set<QString> &set)
{
QStringList list;
for (const auto &item : set) {
list.append(item);
}
return list;
}
void MainWindow::displayStudentDetails(const Student &student) {
// 上半部分Label显示信息
QStringList hobbiesList;
for (const auto &hobby : student.hobbies) {
hobbiesList.append(hobby);
}
QString hobbies = hobbiesList.join("、");
studentInfoLabel->setText(
QString("学号: %1\n姓名: %2\n班级: %3\n爱好: %4")
.arg(student.id)
.arg(student.name)
.arg(student.className)
.arg(hobbies)
);
// 下半部分Table显示成绩
studentTable->setRowCount(student.scores.size()); // 根据成绩数量设置行数
for (int i = 0; i < student.scores.size(); ++i) {
studentTable->setItem(i, 0, new QTableWidgetItem(QString::number(student.scores[i])));
}
}
添加阴影效果
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
#include <QLineEdit>
#include "loadingwidget.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
protected:
void resizeEvent(QResizeEvent *event) override;
private slots:
void onStartLoading();
void onStopLoading();
private:
QPushButton *startButton;
QPushButton *stopButton;
QLineEdit * myLine;
LoadingWidget *loadingWidget;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "MainWindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), startButton(nullptr), stopButton(nullptr), loadingWidget(nullptr)
{
resize(400, 300);
// 创建加载遮罩
loadingWidget = new LoadingWidget(this);
loadingWidget->setGeometry(rect()); // 遮罩覆盖整个主窗口
// 创建按钮
startButton = new QPushButton("加载", this);
startButton->setGeometry(50, 50, 100, 50);
stopButton = new QPushButton("取消", this);
stopButton->setGeometry(250, 50, 100, 50);
myLine = new QLineEdit(this);
myLine->setGeometry(250, 150, 100, 50);
// 绑定信号与槽
connect(startButton, &QPushButton::clicked, this, &MainWindow::onStartLoading);
connect(stopButton, &QPushButton::clicked, this, &MainWindow::onStopLoading);
}
MainWindow::~MainWindow()
{
delete loadingWidget;
}
void MainWindow::resizeEvent(QResizeEvent *event)
{
QMainWindow::resizeEvent(event);
if (loadingWidget) {
loadingWidget->setGeometry(rect()); // 调整遮罩大小
}
}
void MainWindow::onStartLoading()
{
if (loadingWidget) {
loadingWidget->start();
}
}
void MainWindow::onStopLoading()
{
if (loadingWidget) {
loadingWidget->stop();
}
}
loadingwidget.h
#ifndef LOADINGWIDGET_H
#define LOADINGWIDGET_H
#include <QWidget>
#include <QTimer>
class LoadingWidget : public QWidget
{
Q_OBJECT
public:
explicit LoadingWidget(QWidget *parent = nullptr);
protected:
void paintEvent(QPaintEvent *event) override;
void timerEvent(QTimerEvent *event) override;
public slots:
void start();
void stop();
private:
int m_angle = 0; // 当前旋转角度
int m_timerID = -1; // 定时器ID
const int UPDATE_INTERVAL = 60; // 定时器间隔(毫秒)
};
#endif // LOADINGWIDGET_H
···
loadingwidget.
```cpp
#include "LoadingWidget.h"
#include <QPainter>
LoadingWidget::LoadingWidget(QWidget *parent)
: QWidget(parent)
{
setAttribute(Qt::WA_StyledBackground, true);
setWindowFlags(Qt::FramelessWindowHint); // 无边框窗口
setAttribute(Qt::WA_TransparentForMouseEvents, true); // 鼠标事件穿透
setStyleSheet("background-color: rgba(0, 0, 0, 127);"); // 半透明背景
}
void LoadingWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
int size = qMin(width(), height()) / 4;
painter.translate(width() / 2, height() / 2);
painter.rotate(m_angle);
QPen pen;
pen.setWidth(3);
pen.setColor(Qt::white);
painter.setPen(pen);
painter.drawArc(-size, -size, size * 2, size * 2, 0, 120 * 16);
}
void LoadingWidget::timerEvent(QTimerEvent *event)
{
m_angle = (m_angle + 10) % 360;
update();
}
void LoadingWidget::start()
{
if (m_timerID == -1) {
m_timerID = startTimer(UPDATE_INTERVAL);
show();
}
}
void LoadingWidget::stop()
{
if (m_timerID != -1) {
killTimer(m_timerID);
m_timerID = -1;
hide();
}
}
···