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

Qt项目中使用 FieldManager 实现多进程间的字段数据管理

使用场景:
串口收到数据,会将所需要的字段写入FieldManager模块中即更新数据。可能多个接收的报文中分散多个不同字段的结果,实现了解耦。
再一个定时进程中从FieldManager中调用数值,并将数值写入log中实现log的记录。


✅ 一、文件结构

YourProject/
├── FieldManager.h      ✅ 字段管理器头文件(线程安全版)
├── main.cpp            ✅ 主函数
├── mainwindow.h/cpp    ✅ 主窗口类
├── mainwindow.ui       ✅ 界面设计(按钮 + 文本框)
├── YourProject.pro     ✅ Qt 项目文件

✅ 二、1. FieldManager.h

线程安全版本 FieldManager.h

#ifndef FIELDMANAGER_H
#define FIELDMANAGER_H#include <string>
#include <unordered_map>
#include <any>
#include <mutex>
#include <stdexcept>
#include <type_traits>enum class FieldType {U8, S8, U16, S16, U32, S32, FLOAT, DOUBLE
};class FieldManager {
public:static FieldManager& getInstance() {static FieldManager instance;return instance;}// 注册字段void ADD(const std::string& tag, FieldType type) {std::lock_guard<std::mutex> lock(mtx);if (fields.find(tag) != fields.end()) return;switch (type) {case FieldType::U8:     fields[tag] = uint8_t(0); break;case FieldType::S8:     fields[tag] = int8_t(0); break;case FieldType::U16:    fields[tag] = uint16_t(0); break;case FieldType::S16:    fields[tag] = int16_t(0); break;case FieldType::U32:    fields[tag] = uint32_t(0); break;case FieldType::S32:    fields[tag] = int32_t(0); break;case FieldType::FLOAT:  fields[tag] = float(0); break;case FieldType::DOUBLE: fields[tag] = double(0); break;}}// 设置字段值template<typename T>void SET(const std::string& tag, FieldType type, T value) {checkTypeMatch<T>(type);std::lock_guard<std::mutex> lock(mtx);if (fields.find(tag) == fields.end()) throw std::runtime_error("标签未注册");fields[tag] = value;}// 获取字段值template<typename T>T GET(const std::string& tag, FieldType type) {checkTypeMatch<T>(type);std::lock_guard<std::mutex> lock(mtx);if (fields.find(tag) == fields.end()) throw std::runtime_error("标签未注册");return std::any_cast<T>(fields[tag]);}private:std::unordered_map<std::string, std::any> fields;std::mutex mtx; // 互斥锁保护字段读写FieldManager() {}FieldManager(const FieldManager&) = delete;FieldManager& operator=(const FieldManager&) = delete;// 编译期类型检查template<typename T>void checkTypeMatch(FieldType type) {bool match = false;switch (type) {case FieldType::U8:     match = std::is_same_v<T, uint8_t>; break;case FieldType::S8:     match = std::is_same_v<T, int8_t>; break;case FieldType::U16:    match = std::is_same_v<T, uint16_t>; break;case FieldType::S16:    match = std::is_same_v<T, int16_t>; break;case FieldType::U32:    match = std::is_same_v<T, uint32_t>; break;case FieldType::S32:    match = std::is_same_v<T, int32_t>; break;case FieldType::FLOAT:  match = std::is_same_v<T, float>; break;case FieldType::DOUBLE: match = std::is_same_v<T, double>; break;}if (!match) throw std::invalid_argument("类型与FieldType不匹配");}
};#endif // FIELDMANAGER_H

✅ 示例测试(支持多线程)

#include "FieldManager.h"
#include <thread>
#include <iostream>void threadFunc() {auto& fm = FieldManager::getInstance();fm.SET<float>("电压", FieldType::FLOAT, 3.14f);std::cout << "线程中设置电压: " << fm.GET<float>("电压", FieldType::FLOAT) << std::endl;
}int main() {auto& fm = FieldManager::getInstance();fm.ADD("电压", FieldType::FLOAT);std::thread t1(threadFunc);std::thread t2(threadFunc);t1.join();t2.join();std::cout << "主线程读取电压: " << fm.GET<float>("电压", FieldType::FLOAT) << std::endl;return 0;
}

✅ 输出示例

线程中设置电压: 3.14
线程中设置电压: 3.14
主线程读取电压: 3.14

如何使用:

确保你已经在文件顶部添加:

#include <any>  // ✅ 必需
#include <mutex>
#include <unordered_map>
#include <string>

并确保 Qt 项目启用了 C++17。

CONFIG += c++17


✅ 三、2. mainwindow.ui 设计界面

在 Qt Designer 中拖入以下控件:

控件类型ObjectName说明
QPushButtonbtnSet设置字段按钮
QPushButtonbtnGet获取字段按钮
QLineEditlineEditValue输入值
QLabellabelResult显示读取结果

✅ 四、3. mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_btnSet_clicked();void on_btnGet_clicked();private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

✅ 五、4. mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "FieldManager.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 注册一个字段 "电压",类型为 FLOATFieldManager::getInstance().ADD("电压", FieldType::FLOAT);connect(ui->btnSet, &QPushButton::clicked, this, &MainWindow::on_btnSet_clicked);connect(ui->btnGet, &QPushButton::clicked, this, &MainWindow::on_btnGet_clicked);
}MainWindow::~MainWindow() {delete ui;
}void MainWindow::on_btnSet_clicked() {bool ok;float value = ui->lineEditValue->text().toFloat(&ok);if (ok) {FieldManager::getInstance().SET<float>("电压", FieldType::FLOAT, value);ui->labelResult->setText("设置成功");} else {ui->labelResult->setText("请输入有效数字");}
}void MainWindow::on_btnGet_clicked() {try {float v = FieldManager::getInstance().GET<float>("电压", FieldType::FLOAT);ui->labelResult->setText(QString("读取值: %1").arg(v));} catch (std::exception& e) {ui->labelResult->setText("读取失败: " + QString(e.what()));}
}

✅ 六、5. main.cpp

#include "mainwindow.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();return a.exec();
}

✅ 七、6. YourProject.pro(开启 C++17)

QT += core gui widgetsgreaterThan(QT_MAJOR_VERSION, 5): QT += widgetsTARGET = YourProject
TEMPLATE = appCONFIG += c++17SOURCES += main.cpp \mainwindow.cppHEADERS += mainwindow.h \FieldManager.hFORMS += mainwindow.ui

✅ 八、编译运行效果

  • 输入一个数字点击【设置】 → 会将其存入 FieldManager"电压" 字段。
  • 点击【获取】 → 会显示之前设置的值。
http://www.lryc.cn/news/602916.html

相关文章:

  • EXCEL怎么使用数据透视表批量生成工作表
  • 十七、K8s 可观测性:全链路追踪
  • django 按照外键排序
  • 未授权访问
  • 项目如何按时交付?重点关注的几点
  • 进程间通信————system V 共享内存
  • Python day27
  • 在rsync + inotify方案中,如何解决海量小文件同步效率问题?
  • 从视觉到智能:RTSP|RTMP推拉流模块如何助力“边缘AI系统”的闭环协同?
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘nbconvert’问题
  • Java设计模式-通俗举例
  • 铜金矿数据分组优化系统设计与实现
  • 扩展和插件功能
  • 网络 编程
  • C#_运算符重载 operator
  • Joint.cpp - OpenExo
  • Windows 11 下 Anaconda 命令修复指南及常见问题解决
  • MCP error -32000: Connection closed
  • ESP32学习-按键中断
  • 【unitrix】 6.20 非零整数特质(non_zero.rs)
  • Laravel 分页方案整理
  • 小智源码分析——音频部分(二)
  • 数据开源 | “白虎”数据集首批开源,迈出百万数据征途第一步
  • 阿里云正式开源 LoongSuite:打造 AI 时代的高性能低成本可观测采集套件
  • 自学嵌入式 day36 数据库
  • Java面试宝典:MySQL事务底层和高可用原理
  • MR-link-2:多效性顺式孟德尔随机化分析!
  • <PLC><西门子><modbusTCP>在西门子S7-1200系列PLC中,如何设置modbusTCP通讯?
  • 介绍一下static关键字
  • Go 原理之 GMP 并发调度模型