便携式动平衡仪Qt应用层详细设计方案(基于Qt Widgets)
便携式动平衡仪Qt应用层详细设计方案(基于Qt Widgets)
版本:1.0
日期:2023年10月
一、系统概述
1.1 功能需求
- 开机流程:长按电源键启动,全屏显示商标动画(快闪3~4次)。
- 主界面:三栏布局(状态栏、工作区图标、导航栏),支持点击图标跳转。
- 模板系统:保存/加载动平衡参数模板(
.tpl
文件),点击模板直接跳转至测量界面。 - 实时显示:双圆形仪表盘(相位/角度)、数据表格、实时曲线。
1.2 技术选型
- 开发框架:Qt 6.5 + Qt Widgets
- 硬件平台:STM32MP157(Cortex-A7 + M4双核)
- 界面设计工具:Qt Designer
- 文件格式:JSON + AES加密
二、应用层架构设计
2.1 分层架构
+---------------------+
| UI界面层 | <- 使用Qt Designer设计的窗口和控件
+---------------------+
| 业务逻辑层 | <- 模板管理、导航控制、数据处理
+---------------------+
| 硬件服务层 | <- 与M4核通信(共享内存/IPC)、文件读写
+---------------------+
2.2 模块划分
模块 | 功能 | 关键类/组件 |
---|---|---|
启动与主界面模块 | 开机动画、主界面布局、图标响应 | SplashScreen MainWindow |
导航管理模块 | 页面堆栈控制(前进/后退) | QStackedWidget NavigationManager |
模板系统模块 | 模板保存/加载、文件关联、桌面快捷方式生成 | TemplateManager QFileDialog |
实时显示模块 | 相位/角度仪表盘、数据表格、实时曲线 | PhaseMeterWidget DataTableView |
配置模块 | 平衡参数输入、传感器校准界面 | ConfigDialog CalibrationWizard |
三、模块详细设计
3.1 启动与主界面模块
3.1.1 开机动画实现
// SplashScreen.cpp(继承QWidget)
void SplashScreen::showEvent(QShowEvent *event) {QPropertyAnimation *animation = new QPropertyAnimation(this, "opacity");animation->setDuration(1000);animation->setStartValue(1.0);animation->setEndValue(0.3);animation->setLoopCount(3); // 快闪3次animation->start(QAbstractAnimation::DeleteWhenStopped);
}
3.1.2 主界面布局(Qt Designer设计)
-
Qt Designer设计文件:
MainWindow.ui
- 顶部状态栏:
QStatusBar
+QLabel
(日期) +QProgressBar
(电量) - 工作区图标网格:
QGridLayout
+QPushButton
(带图标) - 底部导航栏:
QHBoxLayout
+QPushButton
(前进/后退)
// MainWindow.cpp(通过ui_MainWindow.h生成) void MainWindow::setupUi() {// 初始化网格布局(2行5列)QGridLayout *gridLayout = new QGridLayout(centralWidget);for (int i = 0; i < 8; i++) {QPushButton *btn = new QPushButton(this);btn->setIcon(QIcon(iconPaths[i]));gridLayout->addWidget(btn, i / 5, i % 5);} }
- 顶部状态栏:
3.2 导航管理模块
3.2.1 页面堆栈控制
// NavigationManager.cpp
void NavigationManager::switchToPage(QWidget *page) {QStackedWidget *stack = qobject_cast<QStackedWidget*>(parent());if (!stack->children().contains(page)) {stack->addWidget(page);}stack->setCurrentWidget(page);
}
3.2.2 按钮事件绑定
// MainWindow.cpp
connect(ui->btn1Plane, &QPushButton::clicked, [=]{ConfigDialog *configDialog = new ConfigDialog(this);NavigationManager::switchToPage(configDialog);
});
3.3 模板系统模块
3.3.1 模板文件格式(JSON)
{"version": 1,"rpm": 3000,"plane_mode": 1,"calibration": { "sensor_id": "SENSOR_001", "offset": 0.12 }
}
3.3.2 模板加载与文件关联
// TemplateManager.cpp
void TemplateManager::loadTemplate(const QString &path) {QFile file(path);if (!file.open(QIODevice::ReadOnly)) return;QByteArray data = file.readAll();QJsonDocument doc = QJsonDocument::fromJson(decryptData(data));BalanceTemplate tpl = parseJson(doc);emit templateLoaded(tpl); // 触发界面跳转
}// 文件关联(双击事件)
void FileBrowser::onFileDoubleClicked(const QString &path) {if (path.endsWith(".tpl")) {TemplateManager::instance()->loadTemplate(path);NavigationManager::switchToPage(new BalancePage());}
}
3.4 实时显示模块
3.4.1 自定义仪表盘控件
// PhaseMeterWidget.cpp(继承QWidget)
void PhaseMeterWidget::paintEvent(QPaintEvent*) {QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);painter.setPen(QPen(Qt::red, 8));painter.drawArc(rect(), 90*16, -angle*16); // 角度转换为十六分一度
}
3.4.2 数据表格动态更新
// DataTableView.cpp(继承QTableWidget)
void DataTableView::updateData(const QVector<double> &data) {for (int i = 0; i < data.size(); i++) {QTableWidgetItem *item = new QTableWidgetItem(QString::number(data[i]));setItem(i, 0, item);}
}
四、接口定义与数据流
4.1 硬件服务层接口
接口名称 | 功能 | 实现方式 |
---|---|---|
readSensorData() | 从M4核读取实时振动数据 | 共享内存 + 互斥锁 |
saveToFile() | 保存测量结果到CSV文件 | QFile + QTextStream |
4.2 共享内存通信(A7与M4核)
// SharedData.h
struct SharedData {volatile float phase;volatile float amplitude;pthread_mutex_t lock;
};
五、代码框架与实现
5.1 项目目录结构
项目根目录/
├── src/
│ ├── main.cpp # 应用入口
│ ├── ui/
│ │ ├── MainWindow.ui # 主界面设计文件
│ │ ├── ConfigDialog.ui # 配置界面设计文件
│ │ └── BalancePage.ui # 测量界面设计文件
│ ├── core/
│ │ ├── TemplateManager.cpp # 模板管理逻辑
│ │ └── NavigationManager.cpp # 导航控制
│ ├── widgets/
│ │ ├── PhaseMeterWidget.cpp # 自定义仪表盘
│ │ └── DataTableView.cpp # 数据表格
├── resources/
│ ├── icons.qrc # 图标资源
│ └── styles/ # QSS样式表
└── CMakeLists.txt # 构建配置
5.2 核心代码实现
5.2.1 主程序入口(main.cpp)
int main(int argc, char *argv[]) {QApplication app(argc, argv);// 初始化共享内存SharedData *sharedData = SharedMemory::init();// 加载主窗口MainWindow mainWindow;mainWindow.show();return app.exec();
}
5.2.2 主窗口初始化(MainWindow.cpp)
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {setupUi(this); // 加载MainWindow.ui// 初始化堆栈窗口stackedWidget = new QStackedWidget(this);setCentralWidget(stackedWidget);// 预加载页面stackedWidget->addWidget(new ConfigDialog(this));stackedWidget->addWidget(new BalancePage(this));
}
六、测试计划
6.1 单元测试用例
测试项 | 输入 | 预期输出 |
---|---|---|
模板加载功能 | 合法.tpl文件 | 参数解析正确,跳转至测量界面 |
实时数据显示 | 模拟10kHz数据流 | 界面刷新率≥30 FPS |
6.2 自动化测试脚本
# 使用PySide6进行界面自动化测试
def test_main_window(qtbot):window = MainWindow()qtbot.mouseClick(window.btn1Plane, Qt.LeftButton)assert window.stackedWidget.currentWidget() is ConfigDialog
七、详细设计说明书(DDD)
7.1 系统概述
- 目标:实现便携式动平衡仪的图形化操作与实时数据处理。
- 运行环境:STM32MP157 + Linux 5.15,10英寸触控屏。
7.2 模块设计
- 启动模块:通过
QPropertyAnimation
实现快闪动画。 - 模板模块:使用AES-256加密模板文件,支持双击加载。
- 实时显示模块:自定义
QWidget
绘制仪表盘,QTimer
定时刷新数据。
7.3 接口定义
- 硬件接口:通过共享内存与M4核交换数据(
SharedData
结构体)。 - 文件接口:
QFileDialog
选择文件,QJsonDocument
解析数据。
7.4 性能优化
- 双缓冲绘图:避免仪表盘闪烁。
- 线程分离:UI线程与数据处理线程通过信号槽通信。
八、总结
本方案基于 Qt Widgets 实现,完整覆盖用户需求:
- 开发效率:通过Qt Designer快速设计界面,减少手写布局代码。
- 性能保障:自定义控件优化渲染效率,共享内存实现低延迟通信。
- 可维护性:模块化设计,业务逻辑与界面分离。
下一步建议:
- 使用Qt的
QSS
样式表统一界面风格。 - 结合
QTest
框架完善单元测试。
相关文章:
便携式动平衡仪Qt应用层详细设计方案(基于Qt Widgets)
便携式动平衡仪Qt应用层详细设计方案(基于Qt Widgets) 版本:1.0 日期:2023年10月 一、系统概述 1.1 功能需求 开机流程:长按电源键启动,全屏显示商标动画(快闪3~4次)。主界面&…...

SpringBoot源码解析(十一):准备应用上下文
SpringBoot源码系列文章 SpringBoot源码解析(一):SpringApplication构造方法 SpringBoot源码解析(二):引导上下文DefaultBootstrapContext SpringBoot源码解析(三):启动开始阶段 SpringBoot源码解析(四):解析应用参数args Sp…...

CSS 使用white-space属性换行
一、white-space属性的常见值 * 原本格式: 1、white-space:normal 默认值,空格和换行符会被忽略过滤掉;宽度不够时文本会自动换行 * 宽度足够时,normal 处理后的格式 * 宽度不够时, normal 处理后的格式 2、white-spa…...

论文笔记(七十二)Reward Centering(四)
Reward Centering(四) 文章概括摘要附录A 伪代码 文章概括 引用: article{naik2024reward,title{Reward Centering},author{Naik, Abhishek and Wan, Yi and Tomar, Manan and Sutton, Richard S},journal{arXiv preprint arXiv:2405.09999…...

Matlab——图像保存导出成好看的.pdf格式文件
点击图像的右上角,点击第一个保存按钮键。...

官方文档学习TArray容器
一.TArray中的元素相等 1.重载一下 元素中的 运算符,有时需要重载排序。接下来,我们将id 作为判断结构体的标识。 定义结构体 USTRUCT() struct FXGEqualStructInfo {GENERATED_USTRUCT_BODY() public:FXGEqualStructInfo(){};FXGEqualStructInfo(in…...

unxi-进程间通信
1.进程间通信实现方式 【1】同一主机 linux下通信方式: a.传统的进程间通信方式 管道 --- 进行数据传输的"管道" 无名管道 有名管道 信号 --- b.system v 进程间通信 (posix 进程间通信) 共享内存 (进程间…...

微型分组加密算法TEA、XTEA、XXTEA
微型分组加密算法TEA、XTEA、XXTEA TEA(Tiny Encryption Algorithm)算法是一种分组加密算法,由剑桥大学计算机实验室的David Wheeler和Roger Needham于1994年发明。TEA、XTEA、XXTEA算法采用64位的明文分组和128位的密钥。它使用Feistel…...

conda 基本命令
1、查询当前所有的环境 conda env list 2、创建虚拟环境 conda create -n 环境名 [pythonpython版本号] 其中[pythonpython版本号]可以不写 conda create -n test python3.12 我们输入conda env list看到我们的环境创建成功了,但是发现他是创建在我们默认的C盘的…...
详解 为什么 tcp 会出现 粘包 拆包 问题
TCP 会出现 粘包 和 拆包 问题,主要是因为 TCP 是 面向字节流 的协议,它不关心应用层发送的数据是否有边界,也不会自动分割或合并数据包。由于 TCP 的流控制和传输机制,数据可能在传输过程中被拆分成多个小的 TCP 包,或…...
Linus的基本命令
以下是一些常见的 Linux 命令: 一、文件和目录操作: - ls:列出目录中的文件和子目录,常用参数有 -a (显示所有文件,包括隐藏文件)、 -l (显示详细信息)、 -h ࿰…...

【Linux】缓冲区和文件系统
个人主页~ 缓冲区和文件系统 一、FILE结构1、fd2、缓冲区(一)有换行有return全部打印(二)无换行无return的C接口打印(三)无换行无return的系统调用接口打印(四)有换行无return的C接口…...

函数式编程:概念、特性与应用
1. 函数式编程简介 函数式编程,从名称上看就与函数紧密相关。它是一种我们常常使用却可能并未意识到的编程范式,关注代码的结构组织,强调一个纯粹但在实际中有些理想化的不可变世界,涉及数学、方程和副作用等概念,甚至…...

git中的merge和rebase的区别
在 Git 中,git merge 和 git rebase 都是用于整合分支变更的核心命令,但它们的实现方式和结果有本质区别。以下是两者的详细对比: 一、核心区别 特性git mergegit rebase历史记录保留分支拓扑,生成新的合并提交线性化历史&#x…...

【目标检测】目标检测中的数据增强终极指南:从原理到实战,用Python解锁模型性能提升密码(附YOLOv5实战代码)
🧑 博主简介:曾任某智慧城市类企业算法总监,目前在美国市场的物流公司从事高级算法工程师一职,深耕人工智能领域,精通python数据挖掘、可视化、机器学习等,发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…...

uniapp在app下使用mqtt协议!!!支持vue3
什么?打包空白?分享一下我的解决方法! 第一步 找大师算过了,装4.1版本运气好! 所以根目录执行命令… npm install mqtt4.1.0第二步 自己封装一个mqtt文件方便后期开坛做法! // utils/mqtt.js import mqt…...

VMware虚拟机17.5.2版本下载与安装(详细图文教程包含安装包)
文章目录 前言一、vmware虚拟机下载二、vmware虚拟机安装教程三、vmware虚拟机许可证 前言 VMware Workstation Pro 17 功能强大,广受青睐。本教程将带你一步步完成它的安装,简单易上手,助你快速搭建使用环境。 一、vmware虚拟机下载 VMwar…...

如何加固织梦CMS安全,防webshell、防篡改、防劫持,提升DedeCMS漏洞防护能力
织梦系统(DedeCMS)是一款非常知名的CMS系统,因其功能强大、结构科学合理,深受广大用户喜欢。 虽然织梦CMS(DedeCMS)非常优秀,但是为了保障网站安全,我们还是需要做一些必要的防护措…...

STM32的HAL库开发---ADC采集内部温度传感器
一、STM32内部温度传感器简介 二、温度计算方法 F1系列: 从数据手册中可以找到V25和Avg_Slope F4、F7、H7系列只是标准值不同,自行查阅手册 三、实验简要 1、功能描述 通过ADC1通道16采集芯片内部温度传感器的电压,将电压值换算成温度后&…...
Linux 命令大全完整版(12)
Linux 命令大全 5. 文件管理命令 ln(link) 功能说明:连接文件或目录。语 法:ln [-bdfinsv][-S <字尾备份字符串>][-V <备份方式>][--help][--version][源文件或目录][目标文件或目录] 或 ln [-bdfinsv][-S <字尾备份字符串>][-V…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...

大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...

EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...