QT应用编程: 使用qcustomplot显示动态曲线、设计心电图显示页面

简介: QT应用编程: 使用qcustomplot显示动态曲线、设计心电图显示页面

一、环境介绍

操作系统: win10 64位


QT版本:  QT5.12.6


编译器:  MinGW 32


二、功能介绍

软件端接收设备上传的心电数据、运动数据、体温数据进行处理、存储显示。


完整项目源码下载链接: https://download.csdn.net/download/xiaolong1126626497/18607424

image.png

image.png

image.png

image.png

image.png

三、核心代码

3.1 widget.cpp

#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


目录
相关文章
|
1月前
|
开发框架 Linux API
Qt:构建高效且用户友好的跨平台应用
Qt:构建高效且用户友好的跨平台应用
|
1月前
|
开发框架 网络协议 数据库
Qt:构建跨平台应用的强大框架
Qt:构建跨平台应用的强大框架
|
1月前
|
Web App开发 编解码 安全
视频会议技术 入门探究:WebRTC、Qt与FFmpeg在视频编解码中的应用
视频会议技术 入门探究:WebRTC、Qt与FFmpeg在视频编解码中的应用
259 4
|
1月前
|
算法 数据可视化 程序员
【Qt UI】调色板QPalette类在Qt编程中的应用
【Qt UI】调色板QPalette类在Qt编程中的应用
41 0
|
1月前
|
Web App开发 编解码 安全
【WebRTC 入门教程】全面解析WebRTC:从底层原理到Qt和FFmpeg的集成应用
【WebRTC 入门教程】全面解析WebRTC:从底层原理到Qt和FFmpeg的集成应用
456 1
|
3天前
|
关系型数据库 MySQL 项目管理
数据库大作业——基于qt开发的图书管理系统(四)项目目录的整理与绘制登录页面
数据库大作业——基于qt开发的图书管理系统(四)项目目录的整理与绘制登录页面
|
1月前
|
Windows 安全 C++
Qt字符串类应用与常用基本数据类型
Qt字符串类应用与常用基本数据类型
|
1月前
|
开发框架 物联网 云计算
Qt应用领域分析与实践
Qt应用领域分析与实践
43 0
|
1月前
|
XML 网络协议 关系型数据库
Qt框架概述与应用实例
Qt框架概述与应用实例
31 0
|
1月前
|
测试技术 API UED
【Qt 应用开发 】初步理解 Qt窗口中的模态性应用
【Qt 应用开发 】初步理解 Qt窗口中的模态性应用
84 1