一、环境介绍
操作系统: win10 64位
QT版本: QT5.12.6
编译器: MinGW 32
二、功能介绍
软件端接收设备上传的心电数据、运动数据、体温数据进行处理、存储显示。
完整项目源码下载链接: https://download.csdn.net/download/xiaolong1126626497/18607424
三、核心代码
#include "widget.h" #include "ui_widget.h" #define AppFontName "Microsoft YaHei" #define AppFontSize 9 #define TextColor QColor(255,255,255) #define Plot_NoColor QColor(0,0,0,0) //曲线1的颜色 #define HeartRate_Plot_DotColor QColor(236,110,0) #define HeartRate_Plot_LineColor QColor(246,98,0) #define HeartRate_Plot_BGColor QColor(246,98,0,80) //曲线2的颜色 #define HeartRate_Plot_DotColor_2 Qt::blue #define HeartRate_Plot_LineColor_2 Qt::blue #define HeartRate_Plot_BGColor_2 Qt::blue #define TextWidth 1 #define LineWidth 2 #define DotWidth 5 //一个刻度里的小刻度数量--太小的话显示的时间会重叠 #define HeartRate_Plot_Count 5 //Y轴最大范围值 #define HeartRate_Plot_MaxY 3000 /* * 设置QT界面的样式 */ void Widget::SetStyle(const QString &qssFile) { QFile file(qssFile); if (file.open(QFile::ReadOnly)) { QString qss = QLatin1String(file.readAll()); qApp->setStyleSheet(qss); QString PaletteColor = qss.mid(20,7); qApp->setPalette(QPalette(QColor(PaletteColor))); file.close(); } else { qApp->setStyleSheet(""); } } Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); /*服务器线程*/ //开始信号 connect(this,SIGNAL(StartServerThread()),&tcp_server_class,SLOT(run())); //日志信号 connect(&tcp_server_class,SIGNAL(LogSend(QString)),this,SLOT(Log_Display(QString))); //移动到线程 tcp_server_class.moveToThread(&tcp_server_thread); tcp_server_thread.start(); //启动线程 StartServerThread(); //创建服务器 this->setWindowTitle("健康监控管家"); //波形图界面初始化 InitForm(); InitPlot(); HeartRate_InitPlot(); HeartRate_LoadPlot(); SetStyle(":/blue.css"); //开始加载数据 plot_timer->start(100); } Widget::~Widget() { delete ui; } //日志显示 void Widget::Log_Display(QString text) { QPlainTextEdit *plainTextEdit_log=ui->plainTextEdit_log; //设置光标到文本末尾 plainTextEdit_log->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor); //当文本数量超出一定范围就清除 if(plainTextEdit_log->toPlainText().size()>1024*4) { plainTextEdit_log->clear(); } plainTextEdit_log->insertPlainText(text); //移动滚动条到底部 QScrollBar *scrollbar = plainTextEdit_log->verticalScrollBar(); if(scrollbar) { scrollbar->setSliderPosition(scrollbar->maximum()); } } //查看服务器状态 void Widget::on_toolButton_server_stat_clicked() { QString text="服务器IP地址列表:\n"; QList<QHostAddress> list = QNetworkInterface::allAddresses(); for(int i=0;i<list.count();i++) { QHostAddress addr=list.at(i); if(addr.protocol() == QAbstractSocket::IPv4Protocol) { text+=addr.toString()+"\n"; } } text+="服务器端口号:8888\n"; if(ClientSocket) { if(ClientSocket->socketDescriptor()==-1) { text+="设备未连接\n"; } else { text+="设备连接成功\n"; } } else { text+="设备未连接\n"; } QMessageBox::about(this,"状态信息",text); } //窗口关闭事件 void Widget::closeEvent(QCloseEvent *event) { tcp_server_thread.quit(); tcp_server_thread.wait(); } void Widget::InitForm() { //初始化随机数种子 QTime time = QTime::currentTime(); qsrand(time.msec() + time.second() * 1000); //初始化动态曲线定时器 plot_timer = new QTimer(this); connect(plot_timer, SIGNAL(timeout()), this, SLOT(HeartRate_LoadPlot())); plots.append(ui->plot2); } void Widget::InitPlot() { //设置纵坐标名称 plots.at(0)->yAxis->setLabel("心电数据(单位:%)"); //设置纵坐标范围 plots.at(0)->yAxis->setRange(0, HeartRate_Plot_MaxY); //设置支持鼠标移动缩放波形界面 plots.at(0)->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom); //设置背景颜色 #if 1 foreach (QCustomPlot *plot, plots) { //设置字体大小 QFont font = QFont(AppFontName, AppFontSize - 2); plot->legend->setFont(font); plot->xAxis->setLabelFont(font); plot->yAxis->setLabelFont(font); plot->xAxis->setTickLabelFont(font); plot->yAxis->setTickLabelFont(font); //设置坐标颜色/坐标名称颜色 plot->yAxis->setLabelColor(TextColor); plot->xAxis->setTickLabelColor(TextColor); plot->yAxis->setTickLabelColor(TextColor); plot->xAxis->setBasePen(QPen(TextColor, TextWidth)); plot->yAxis->setBasePen(QPen(TextColor, TextWidth)); plot->xAxis->setTickPen(QPen(TextColor, TextWidth)); plot->yAxis->setTickPen(QPen(TextColor, TextWidth)); plot->xAxis->setSubTickPen(QPen(TextColor, TextWidth)); plot->yAxis->setSubTickPen(QPen(TextColor, TextWidth)); //设置画布背景色 QLinearGradient plotGradient; plotGradient.setStart(0, 0); plotGradient.setFinalStop(0, 350); plotGradient.setColorAt(0, QColor(80, 80, 80)); plotGradient.setColorAt(1, QColor(50, 50, 50)); plot->setBackground(plotGradient); //设置坐标背景色 QLinearGradient axisRectGradient; axisRectGradient.setStart(0, 0); axisRectGradient.setFinalStop(0, 350); axisRectGradient.setColorAt(0, QColor(80, 80, 80)); axisRectGradient.setColorAt(1, QColor(30, 30, 30)); plot->axisRect()->setBackground(axisRectGradient); //设置图例提示位置及背景色 plot->axisRect()->insetLayout()->setInsetAlignment(0, Qt::AlignTop | Qt::AlignRight); plot->legend->setBrush(QColor(255, 255, 255, 200)); plot->replot(); } #endif } void Widget::HeartRate_InitPlot() { plots.at(0)->addGraph(); plots.at(0)->graph(0)->setName("心电数据1"); plots.at(0)->graph(0)->setPen(QPen(HeartRate_Plot_LineColor, LineWidth)); plots.at(0)->graph(0)->setScatterStyle( QCPScatterStyle(QCPScatterStyle::ssCircle, QPen(HeartRate_Plot_DotColor, LineWidth), QBrush(HeartRate_Plot_DotColor), DotWidth)); //设置动态曲线的横坐标格式及范围 plots.at(0)->xAxis->setTickLabelType(QCPAxis::ltDateTime); plots.at(0)->xAxis->setDateTimeFormat("HH:mm:ss"); plots.at(0)->xAxis->setAutoTickStep(true); plots.at(0)->xAxis->setTickStep(0.5); plots.at(0)->xAxis->setRange(0, HeartRate_Plot_Count, Qt::AlignRight); plots.at(0)->addGraph();//相当于添加一条新的曲线 plots.at(0)->graph(1)->setName("心电数据2"); plots.at(0)->graph(1)->setPen(QPen(HeartRate_Plot_LineColor_2, LineWidth)); plots.at(0)->graph(1)->setScatterStyle( QCPScatterStyle(QCPScatterStyle::ssCircle, QPen(HeartRate_Plot_DotColor_2, LineWidth), QBrush(HeartRate_Plot_DotColor_2), DotWidth)); //设置是否需要显示曲线的图例说明 foreach (QCustomPlot *plot, plots) { plot->legend->setVisible(true); plot->replot(); } //得到数据指针 mData_0 = plots.at(0)->graph(0)->data(); mData_1 = plots.at(0)->graph(1)->data(); } void addToDataBuffer(QCPDataMap *mData,double x, double y) { QCPData newData; newData.key = x; newData.value = y; mData->insert(x, newData); } //加载曲线数据 void Widget::HeartRate_LoadPlot() { int i; bool flag=false; for(i=0;i<5;i++) { //得到秒单位的时间 HeartRate_plot_key = QDateTime::currentDateTime().toMSecsSinceEpoch() / 1000.0; //心电数据1 HeartRate_plot_value=uart_queue_data.read_queueA(); if(HeartRate_plot_value>0) { flag=true; addToDataBuffer(mData_0,HeartRate_plot_key,HeartRate_plot_value); } //心电数据2 HeartRate_plot_value=uart_queue_data.read_queueB(); if(HeartRate_plot_value>0) { flag=true; addToDataBuffer(mData_1,HeartRate_plot_key,HeartRate_plot_value); } } if(flag) { plots.at(0)->xAxis->setRange(HeartRate_plot_key, HeartRate_Plot_Count , Qt::AlignRight); plots.at(0)->rescaleAxes(false); //设置图表完全可见 plots.at(0)->replot(); } /* A:心电数据1,B:新电数据2,C:运动步数,D:运动距离,E:体表温度 例如: "A:1633215,B:1833215,C:45,D:28,E:66.55" */ int val=uart_queue_data.read_queueC(); if(val>0) { ui->lcdNumber_bumber->display(val); } val=uart_queue_data.read_queueD(); if(val>0) { ui->lcdNumber_len->display(val); } double tmp_val=uart_queue_data.read_queueE(); if(tmp_val>0) { ui->lcdNumber_temp->display(tmp_val); } } void Widget::on_toolButton_src_data_clicked() { ui->stackedWidget->setCurrentIndex(0); } void Widget::on_toolButton_image_data_clicked() { ui->stackedWidget->setCurrentIndex(1); } void Widget::on_toolButton_clear_clicked() { mData_0->clear(); mData_1->clear(); }
3.2 widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include "server.h" #include <QPlainTextEdit> #include <QTextCursor> #include <QScrollBar> #include <QPalette> #include "qcustomplot.h" #include "smoothcurvecreator.h" QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); void SetStyle(const QString &qssFile); QThread tcp_server_thread; //服务器工作线程 TCPServer tcp_server_class; //绘制实时曲线 QTimer *plot_timer; QList <QCustomPlot *> plots; double HeartRate_plot_key; unsigned int HeartRate_plot_value; //曲线数据点缓冲区 QCPDataMap *mData_0; QCPDataMap *mData_1; signals: void StartServerThread(); //启动服务器线程 private slots: void Log_Display(QString text); void on_toolButton_server_stat_clicked(); void HeartRate_InitPlot(); void HeartRate_LoadPlot(); void InitPlot(); void InitForm(); void on_toolButton_src_data_clicked(); void on_toolButton_image_data_clicked(); void on_toolButton_clear_clicked(); protected: void closeEvent(QCloseEvent *event); //窗口关闭 private: Ui::Widget *ui; }; #endif // WIDGET_H