构建DataBus总线 怎么"用起来"。你照着做,跑通后你就会知道它到底在干啥。
1)先准备:定义要传的数据结构(Sample)
data/MonitorSample.h
cpp
#pragma once
#include <QDateTime>
#include <QString>
#include <QMetaType>
struct MonitorSample {
QDateTime ts;
double temperature = 0.0;
double voltage = 0.0;
double current = 0.0;
QString status;
};
Q_DECLARE_METATYPE(MonitorSample)
2)准备 DataBus(就是一个"广播器")
data/DataBus.h
cpp
#pragma once
#include <QObject>
#include "MonitorSample.h"
class DataBus : public QObject {
Q_OBJECT
public:
static DataBus& instance() { static DataBus b; return b; }
signals:
void sampleReady(const MonitorSample& s);
private:
explicit DataBus(QObject* parent=nullptr) : QObject(parent) {}
};
3)在 main.cpp 注册类型(Qt5 必须)
main.cpp 里:
cpp
#include <QApplication>
#include <QMetaType>
#include "data/MonitorSample.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qRegisterMetaType<MonitorSample>("MonitorSample"); // ✅ 很关键
...
return a.exec();
}
4)发布数据(emit):谁产生数据谁发
比如你在采集模块里(或先用 QTimer 测试):
cpp
#include "data/DataBus.h"
MonitorSample s;
s.ts = QDateTime::currentDateTime();
s.temperature = 36.2;
s.voltage = 3.30;
s.current = 0.52;
s.status = "OK";
emit DataBus::instance().sampleReady(s); // ✅ 发广播
这行就是 DataBus 的"使用点"之一:发布
5)订阅数据(connect):谁想用数据谁接
比如在 RecordUI 或 MainWindow 里接收:
cpp
#include "data/DataBus.h"
#include <QDebug>
connect(&DataBus::instance(), &DataBus::sampleReady,
this, [this](const MonitorSample& s){
qInfo() << "got sample:" << s.temperature << s.voltage;
// 在这里写 CSV 或更新 UI
},
Qt::QueuedConnection); // ✅ 跨线程安全
这行就是 DataBus 的"使用点"之二:订阅
6)把它接到 CSV 保存(你最想要的)
你已经有 CsvRecorder recorder; 的话,订阅里这么写:
cpp
connect(&DataBus::instance(), &DataBus::sampleReady,
this, [this](const MonitorSample& s){
if (!recorder->isRunning()) return;
recorder->writeRow({
s.ts.toString("yyyy-MM-dd HH:mm:ss.zzz"),
QString::number(s.temperature, 'f', 2),
QString::number(s.voltage, 'f', 3),
QString::number(s.current, 'f', 3),
s.status
});
},
Qt::QueuedConnection);
你真正要记住的就两句话
- emit:产生数据的地方发出去
- connect:需要数据的地方接收处理
这就是 DataBus 的全部用法。