当前位置: 首页 > article >正文

手把手教你用Qt QTableWidget打造一个带交互的‘课程表’应用(附完整源码)

用Qt QTableWidget构建智能课程表从基础布局到高级交互实战大学校园里课程表是每位师生离不开的日常工具。传统的纸质课程表或静态电子表格往往功能单一缺乏个性化设置和动态交互能力。本文将带你用Qt的QTableWidget控件打造一个功能丰富的智能课程表应用不仅能直观展示每周课程安排还能实现选课退课、课程详情查看、个性化样式设置等实用功能。这个项目特别适合已经掌握Qt基础、想通过实战提升技能的开发者我们将从零开始逐步实现以下核心功能动态课程展示按时间轴清晰呈现每周课程可视化状态标记通过颜色区分必修课、选修课和已选课程上下文交互右键菜单实现快速选课/退课操作智能数据存储利用QTableWidgetItem扩展属性保存完整课程信息响应式设计单元格点击事件触发课程详情展示1. 项目环境搭建与基础布局1.1 创建Qt Widgets Application项目首先在Qt Creator中新建项目选择Qt Widgets Application模板。项目命名建议使用SmartCourseSchedule这样的描述性名称便于后续维护。创建完成后我们会在主窗口类中集成QTableWidget控件。// mainwindow.h #include QMainWindow #include QTableWidget class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent nullptr); private: QTableWidget *courseTable; void initCourseTable(); };1.2 初始化课程表基本结构大学课程表通常以周为单位横向为星期周一至周五纵向为节次每天6-8节课。我们在MainWindow构造函数中初始化这个7x6的表格结构5个上课日2个表头列6节课1个表头行// mainwindow.cpp MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { // 创建7列星期时间轴x6行节次表头 courseTable new QTableWidget(6, 7, this); setCentralWidget(courseTable); initCourseTable(); } void MainWindow::initCourseTable() { // 设置表头标签 QStringList headers; headers 节次/星期 周一 周二 周三 周四 周五; courseTable-setHorizontalHeaderLabels(headers); // 设置垂直表头节次时间 QStringList verticalHeaders; verticalHeaders 08:00-09:35 10:00-11:35 13:30-15:05 15:20-16:55 17:10-18:45; courseTable-setVerticalHeaderLabels(verticalHeaders); // 调整列宽和行高 courseTable-horizontalHeader()-setSectionResizeMode(QHeaderView::Stretch); courseTable-verticalHeader()-setDefaultSectionSize(60); }提示使用QHeaderView::Stretch模式可以让表格自动适应窗口大小这在响应式设计中非常实用。1.3 基础样式配置为了让课程表更加美观我们需要对表格进行一些基础样式设置// 设置表格不可编辑 courseTable-setEditTriggers(QAbstractItemView::NoEditTriggers); // 设置选择行为单选整行 courseTable-setSelectionBehavior(QAbstractItemView::SelectRows); courseTable-setSelectionMode(QAbstractItemView::SingleSelection); // 设置交替行颜色 courseTable-setAlternatingRowColors(true); courseTable-setStyleSheet( QTableWidget { alternate-background-color: #f0f0f0; selection-background-color: #b8d6f9; } QHeaderView::section { background-color: #5d9cec; color: white; padding: 4px; } );2. 课程数据模型与可视化呈现2.1 设计课程数据结构一个完整的课程信息应该包含以下属性属性名类型描述courseIdQString课程唯一标识courseNameQString课程名称teacherQString授课教师locationQString上课地点creditint学分typeint课程类型0必修/1选修selectedbool是否已选我们可以创建一个简单的CourseInfo类来封装这些属性// courseinfo.h #include QString #include QColor class CourseInfo { public: CourseInfo(const QString id, const QString name, const QString teacher, const QString location, int credit, int type, bool selected false); // 获取显示文本 QString displayText() const; // 根据课程类型获取背景色 QColor backgroundColor() const; // 成员变量略 ... };2.2 在表格项中存储扩展数据QTableWidgetItem不仅可以显示文本还能通过setData()方法存储任意QVariant数据。我们利用这个特性将完整的CourseInfo对象存储在单元格中void MainWindow::addCourse(int day, int period, const CourseInfo course) { QTableWidgetItem *item new QTableWidgetItem(course.displayText()); // 存储完整课程信息 item-setData(Qt::UserRole, QVariant::fromValue(course)); // 设置样式 item-setBackground(course.backgroundColor()); item-setTextAlignment(Qt::AlignCenter); courseTable-setItem(period, day, item); }2.3 课程类型可视化方案不同类型的课程使用不同背景色让用户一目了然QColor CourseInfo::backgroundColor() const { if (selected) { return QColor(#d4edda); // 已选课程-浅绿色 } switch(type) { case 0: return QColor(#f8d7da); // 必修课-浅红色 case 1: return QColor(#fff3cd); // 选修课-浅黄色 default: return Qt::white; } }3. 实现交互功能3.1 右键菜单实现选课/退课为表格添加右键菜单是提升用户体验的有效方式。我们需要重写contextMenuEvent事件// mainwindow.h protected: void contextMenuEvent(QContextMenuEvent *event) override; private slots: void onSelectCourse(); void onDropCourse();// mainwindow.cpp void MainWindow::contextMenuEvent(QContextMenuEvent *event) { QTableWidgetItem *item courseTable-itemAt(event-pos()); if (!item) return; CourseInfo course item-data(Qt::UserRole).valueCourseInfo(); if (course.courseId.isEmpty()) return; QMenu menu(this); if (course.selected) { menu.addAction(退选该课程, this, MainWindow::onDropCourse); } else { menu.addAction(选该课程, this, MainWindow::onSelectCourse); } menu.exec(event-globalPos()); }3.2 选课/退课逻辑实现选课和退课操作实际上是对单元格数据和样式的更新void MainWindow::onSelectCourse() { QTableWidgetItem *item courseTable-currentItem(); if (!item) return; CourseInfo course item-data(Qt::UserRole).valueCourseInfo(); course.selected true; item-setData(Qt::UserRole, QVariant::fromValue(course)); item-setBackground(course.backgroundColor()); // 这里可以添加选课成功的提示或日志记录 statusBar()-showMessage(tr(已成功选课%1).arg(course.courseName), 3000); }3.3 单元格点击事件与详情展示当用户点击课程单元格时我们可以在界面底部或独立对话框中展示完整课程信息// 连接单元格点击信号 connect(courseTable, QTableWidget::cellClicked, this, MainWindow::onCellClicked); void MainWindow::onCellClicked(int row, int column) { QTableWidgetItem *item courseTable-item(row, column); if (!item) return; CourseInfo course item-data(Qt::UserRole).valueCourseInfo(); if (course.courseId.isEmpty()) return; // 创建详情对话框 QDialog detailDialog(this); QFormLayout *layout new QFormLayout(detailDialog); // 添加课程信息字段 layout-addRow(课程名称:, new QLabel(course.courseName)); layout-addRow(授课教师:, new QLabel(course.teacher)); layout-addRow(上课地点:, new QLabel(course.location)); layout-addRow(学分:, new QLabel(QString::number(course.credit))); detailDialog.exec(); }4. 高级功能扩展4.1 课程数据持久化实际应用中我们需要将课程数据保存到文件或数据库。Qt提供了多种持久化方案// 保存课程表到JSON文件 void MainWindow::saveToFile(const QString filename) { QJsonArray courseArray; for (int row 0; row courseTable-rowCount(); row) { for (int col 0; col courseTable-columnCount(); col) { QTableWidgetItem *item courseTable-item(row, col); if (item) { CourseInfo course item-data(Qt::UserRole).valueCourseInfo(); if (!course.courseId.isEmpty()) { courseArray.append(course.toJson()); } } } } QFile file(filename); if (file.open(QIODevice::WriteOnly)) { file.write(QJsonDocument(courseArray).toJson()); } }4.2 多视图同步如果需要同时显示周视图和月视图可以使用共享的QAbstractItemModel// 创建共享模型 QStandardItemModel *sharedModel new QStandardItemModel(this); // 周视图表格 QTableView *weekView new QTableView; weekView-setModel(sharedModel); // 月视图表格 QTableView *monthView new QTableView; monthView-setModel(sharedModel);4.3 性能优化技巧当课程数据量较大时可以采取以下优化措施延迟加载只渲染可见区域的课程项代理渲染使用QStyledItemDelegate自定义绘制逻辑批量更新在大量修改前调用setUpdatesEnabled(false)// 批量更新示例 courseTable-setUpdatesEnabled(false); // 执行大量单元格修改操作 courseTable-setUpdatesEnabled(true); courseTable-viewport()-update(); // 触发重绘5. 项目打包与部署完成开发后我们需要将应用程序打包发布。Qt提供了多种打包工具Windows使用windeployqt收集依赖库macOS使用macdeployqt创建.app bundleLinux使用linuxdeployqt或手动打包# Windows部署示例 windeployqt --release SmartCourseSchedule.exe对于更专业的发布可以考虑使用InstallShield或Inno Setup等安装包制作工具它们能提供更好的用户体验和自动更新功能。

相关文章:

手把手教你用Qt QTableWidget打造一个带交互的‘课程表’应用(附完整源码)

用Qt QTableWidget构建智能课程表:从基础布局到高级交互实战 大学校园里,课程表是每位师生离不开的日常工具。传统的纸质课程表或静态电子表格往往功能单一,缺乏个性化设置和动态交互能力。本文将带你用Qt的QTableWidget控件打造一个功能丰富…...

Flowable工作流核心表结构全解析:从ACT_RE到ACT_HI,看完这篇就懂了

Flowable工作流引擎核心表结构深度解析:从数据视角掌握流程运转机制 1. 工作流引擎的数据架构设计哲学 现代BPM系统的核心在于如何高效管理流程状态与历史轨迹,Flowable通过精心设计的表结构实现了这一目标。与大多数开发者仅关注API调用不同&#xff0c…...

如何突破TIDAL平台限制,高效构建24-bit高解析度个人音乐库?

如何突破TIDAL平台限制,高效构建24-bit高解析度个人音乐库? 【免费下载链接】tidal-dl-ng TIDAL Media Downloader Next Generation! Up to HiRes / TIDAL MAX 24-bit, 192 kHz. 项目地址: https://gitcode.com/gh_mirrors/ti/tidal-dl-ng TIDAL …...

从手动保存到一键下载:抖音无水印视频获取的革命性工具

从手动保存到一键下载:抖音无水印视频获取的革命性工具 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback supp…...

STM32F4驱动ST7735S小屏幕:从SPI配置到图片显示,一个完整项目带你玩转TFTLCD

STM32F4驱动ST7735S小屏幕:从SPI配置到图片显示实战指南 手里这块1.44寸的ST7735S屏幕已经吃灰三个月了?跟着我做这个温湿度监测项目,保证让你的开发板和小屏幕都活起来。不需要死记硬背那些SPI参数,咱们直接动手做出能显示动态数…...

从音频采集到FPGA:手把手教你复刻一个8通道AD采样系统(附完整代码与PCB)

从音频采集到FPGA:手把手教你复刻一个8通道AD采样系统(附完整代码与PCB) 在嵌入式系统与信号处理领域,多通道数据采集一直是工程师面临的核心挑战之一。无论是工业自动化中的传感器网络,还是医疗设备中的生物电信号监测…...

手把手教你排查OpenWRT虚拟机网卡直通失败:从lspci到QEMU命令的避坑指南

手把手教你排查OpenWRT虚拟机网卡直通失败:从lspci到QEMU命令的避坑指南 虚拟化环境中实现网卡直通是许多网络爱好者和企业IT管理员追求的高性能解决方案。当你在Debian宿主机上尝试为OpenWRT虚拟机配置PCIe网卡直通时,可能会遇到各种意料之外的障碍——…...

别再乱码了!从ASCII到UTF-8,5分钟搞懂程序员必知的字符编码原理

别再乱码了!从ASCII到UTF-8,程序员必知的字符编码实战指南 当你从数据库导出CSV文件时,中文字符突然变成乱码;当API返回的JSON数据在控制台显示为"????";当同事发来的日志文件里夹杂着�符号—…...

深入聊聊Xilinx MIPI CSI-2 RX Subsystem IP:在Zynq UltraScale上解码OV5640视频的配置要点与性能调优

Xilinx MIPI CSI-2 RX Subsystem IP在Zynq UltraScale平台上的深度优化实践 OV5640摄像头作为工业视觉领域最常见的图像传感器之一,其MIPI接口的高带宽特性对FPGA设计提出了严苛要求。Xilinx提供的MIPI CSI-2 RX Subsystem IP虽然大幅降低了开发门槛,但…...

从硬件到代码:手把手拆解DMA外挂的完整链条(含Apex实战代码分析)

从硬件到代码:手把手拆解DMA外挂的完整链条(含Apex实战代码分析) 在游戏安全领域,DMA(直接内存访问)技术正逐渐成为高端作弊工具的核心组件。这种原本用于工业数据采集的技术,因其能够绕过CPU直…...

OpenClaw汉化版部署指南:本地AI助手从入门到精通

1. 项目概述 如果你是一个对AI智能体(AI Agent)技术感兴趣的开发者,或者你只是想在自己的电脑上部署一个能通过WhatsApp、Telegram等聊天软件和你对话的私人AI助手,那么你很可能已经听说过OpenClaw。这个在GitHub上收获了近20万星…...

2026数据科学学习路线图:从Python基础到深度学习部署实战

1. 数据科学学习路线图:一份面向2026年的实战指南 如果你正站在数据科学的大门前,看着里面琳琅满目的技术栈和层出不穷的新名词感到迷茫,不知道从哪里开始,也不知道该往哪里走,那么你来对地方了。这份路线图不是一份简…...

从图像压缩到推荐系统:特征值分解到底在哪些实际项目里悄悄干活?

从图像压缩到推荐系统:特征值分解到底在哪些实际项目里悄悄干活? 当你用手机拍下一张照片,系统瞬间完成高清压缩;当你在电商平台浏览商品,首页突然出现"猜你喜欢"的精准推荐;当你在搜索引擎输入关…...

3大核心功能解锁:用MATVT将电视遥控器变身精准鼠标控制器

3大核心功能解锁:用MATVT将电视遥控器变身精准鼠标控制器 【免费下载链接】matvt Virtual Mouse for Android TV that can be controlled via remote itself. 项目地址: https://gitcode.com/gh_mirrors/ma/matvt 您是否曾为Android TV上那些难以点击的小按钮…...

为什么83%的AI公司IPO被问询AISMM?2026奇点大会披露的3项硬指标已成交易所默认红线

更多请点击: https://intelliparadigm.com 第一章:2026奇点智能技术大会:AISMM与IPO准备 2026奇点智能技术大会(Singularity Intelligence Summit 2026)正式宣布启动AISMM(Autonomous Intelligent System …...

TFT Overlay:当云顶之弈的复杂性遇到开源社区的温暖

TFT Overlay:当云顶之弈的复杂性遇到开源社区的温暖 【免费下载链接】TFT-Overlay Overlay for Teamfight Tactics 项目地址: https://gitcode.com/gh_mirrors/tf/TFT-Overlay 在《英雄联盟:云顶之弈》的世界里,每个回合都是一次思维的…...

LuaDec51终极指南:快速掌握Lua 5.1字节码反编译的完整方法

LuaDec51终极指南:快速掌握Lua 5.1字节码反编译的完整方法 【免费下载链接】luadec51 Lua Decompiler for Lua version 5.1 项目地址: https://gitcode.com/gh_mirrors/lu/luadec51 你是否曾经面对一个加密的Lua字节码文件,却束手无策&#xff1f…...

百度网盘秒传脚本:永久有效的文件分享终极解决方案

百度网盘秒传脚本:永久有效的文件分享终极解决方案 【免费下载链接】rapid-upload-userscript-doc 秒传链接提取脚本 - 文档&教程 项目地址: https://gitcode.com/gh_mirrors/ra/rapid-upload-userscript-doc 你是否曾因百度网盘分享链接7天后失效而烦恼…...

老漏洞新谈:CVE-2010-0738的HEAD请求绕过与JBoss JMX Console的权限之殇

CVE-2010-0738:HEAD请求的艺术与JMX Console的防御盲区 十年前那个春寒料峭的三月,当安全研究员在JBoss JMX控制台前反复切换HTTP请求方法时,一个看似平常的HEAD请求意外触发了系统响应。这个后来被编号为CVE-2010-0738的漏洞,不…...

iOS原生AI助手开发实战:从UIKit选型到Stable Diffusion本地部署

1. 项目概述:一个原生、全能的iOS端AI助手最近在App Store上架了一款名为“Chat走啦”的iOS应用,它本质上是一个功能相当全面的ChatGPT原生客户端。和很多基于WebView简单套壳的应用不同,这个项目从底层网络请求到上层UI交互,都采…...

ChatGPT账号自动化创建:Selenium实战与反检测策略详解

1. 项目概述与核心价值最近在折腾一些AI应用开发,发现很多有意思的想法都卡在了一个看似简单、实则麻烦的环节上:获取一个可用的ChatGPT账号。无论是想测试最新的API功能,还是想搭建一个内部使用的对话机器人,账号都是绕不过去的门…...

Maven多模块项目实战:手把手教你配置pom.xml中的parent.relativePath,告别路径错误

Maven多模块项目实战:parent.relativePath配置全指南与深度解析 当你在深夜的办公室里,面对一个复杂的Maven多模块项目构建失败,控制台不断抛出"parent.relativePath points at wrong local POM"错误时,那种挫败感每个…...

别再只会ping了!用iperf3给你的CentOS 7服务器做个专业‘网络体检’

专业级网络性能诊断:用iperf3解锁CentOS服务器的隐藏问题 当服务器响应变慢、应用数据传输卡顿时,大多数运维人员的第一反应是执行ping测试。然而,这种基础手段只能告诉你网络是否连通,却无法揭示更深层次的性能瓶颈。真正的网络…...

5步让Windows字体拥有macOS般的清晰锐利:MacType终极配置指南

5步让Windows字体拥有macOS般的清晰锐利:MacType终极配置指南 【免费下载链接】mactype Better font rendering for Windows. 项目地址: https://gitcode.com/gh_mirrors/ma/mactype 还在为Windows系统下模糊的字体显示效果而烦恼吗?MacType作为一…...

保姆级教程:用MATLAB手把手仿真FMCW雷达测距测速(附77GHz毫米波雷达代码)

77GHz毫米波雷达实战:MATLAB实现FMCW测距测速全流程解析 第一次接触FMCW雷达仿真时,我被那些复杂的公式和理论推导搞得晕头转向——直到发现用MATLAB代码反向理解原理才是最高效的学习路径。本文将带你用不到200行代码,从零构建完整的77GHz毫…...

ARM-2D vs. LVGL/emWin:为你的Cortex-M项目选择GUI底层加速库的完整指南

ARM-2D与主流GUI框架深度整合实战指南 引言:嵌入式GUI加速的痛点与破局 在智能手表、工业HMI和家用电器等嵌入式场景中,流畅的图形界面已成为基础需求。但当我们为Cortex-M系列MCU设计GUI时,常陷入两难困境:要么使用LVGL、emWin等…...

避坑指南:ESP32用Modbus读485设备,为什么你的软串口总收不到数据?

ESP32 Modbus通信避坑指南:软串口数据丢失的深层分析与解决方案 当你在ESP32项目中使用Modbus协议通过485接口读取传感器数据时,是否遇到过这样的场景:硬件连接正确,代码看似无误,但软串口(SoftwareSerial)就是收不到任…...

别再只显示数字了!用TM1638+Arduino打造一个迷你桌面时钟/温湿度计(附完整代码)

用TM1638打造智能桌面时钟与温湿度监控系统 在电子DIY的世界里,总有一些小模块能以极低的成本带来巨大的乐趣。TM1638就是这样一款神奇的组合模块——它集成了8位数码管、8个LED指示灯和8个独立按键,价格却只要一杯奶茶的钱。今天,我们就用这…...

VisualCppRedist AIO终极指南:一站式解决Windows VC++运行库难题

VisualCppRedist AIO终极指南:一站式解决Windows VC运行库难题 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过Windows应用程序无法…...

Mac/Win双平台实测:彻底解决Scrcpy投屏的LIBUSB权限错误(2024最新)

Mac/Win双平台实战:2024年Scrcpy投屏LIBUSB权限错误的终极解法 当你在深夜赶工调试安卓应用,突然遭遇Scrcpy投屏闪退并弹出LIBUSB_ERROR_ACCESS错误时,那种烦躁感我深有体会。作为跨平台安卓开发的必备工具,Scrcpy在不同操作系统下…...