QtCharts绘制动态心电图[1]——初步应用

文章目录

  • 在UI文件中添加Qtchart
  • 初始化心电图函数
  • 心电图动态绘制主要代码
    • 开启定时器并绑定定时槽函数
    • 波形绘制函数
  • 程序相关说明
  • 写在最后

先放效果图:
QtCharts绘制动态心电图[1]——初步应用_第1张图片
该效果图和目前网上的动态波形略有不同,网上的多是从左往右或是从右往左的动态波形显示,但是该图更加贴近目前监护的心电波形绘制,即 从左往右进行绘制,到达最右后再次从左往右进行绘制
看了下以前的实现方法,多是使用第三方库QWT、QCustomPlot,但是QtCharts已经加入Qt模块中了,这个包功能还是很强大的,这里就使用QtCharts进行绘制,要注意在安装的时候就安装Qtcharts以及工程要添加QtCharts模块。
主思想是利用QtCharts自带的函数和方法,先初始化心电图网格线,绑定数据,然后开启定时器进行绘制。在绘制到最右边的时候,使用Qtcharts数据集series进行已有数据替换可以了。

在UI文件中添加Qtchart

QtCharts依赖于QtChartView实现,但是在UI文件中是没有 QtChartView这个类型的。所以我们需要进行一些额外的操作来实现我们的目的。因为QtChartView继承自QGraphicsView,所以我们可以在界面添加一个Graphics View
在这里插入图片描述
然后在右边的对象查看器中,选中这个QGraphicsView然后右键,就会出现菜单,选择提升为,这个操作就可以实现添加继承自QGraphicsView的模块。
QtCharts绘制动态心电图[1]——初步应用_第2张图片
进行下方的操作就可以在UI文件中添加一个继承自QGraphicsView的QtChartView了QtCharts绘制动态心电图[1]——初步应用_第3张图片
记得在头文件中包含下方的代码,这样才可以正常使用QtCharts。

#include 

初始化心电图函数

为了达到心电图的效果,首先我们根据期望的目标对表格进行初始化,实现图标的红色虚线线框,让心电波形更加凸显。
其中设置线型函数需要说明一下
axisX_ECG->setLinePen(QPen(Qt::red, 1, Qt::DashDotDotLine, Qt::SquareCap, Qt::RoundJoin))

  • 第一个参数代表颜色
  • 第二个参数代表线宽
  • 第三个参数代表线型

不同线型区别
QtCharts绘制动态心电图[1]——初步应用_第4张图片

  • 第四个参数代表线端点样式

QtCharts绘制动态心电图[1]——初步应用_第5张图片

  • 第五个参数线转接点样式

QtCharts绘制动态心电图[1]——初步应用_第6张图片

  • 具体的参数说明参看这个链接QPen Class

折线图初始化函数

void DynamicECG::initEcgWaveLineChart() {
	axisY_ECG = new QValueAxis();
	axisX_ECG = new QValueAxis();
	ecgSeries = new QLineSeries();//这里也可以也考虑改为平滑曲线
	ecgWaveLineChart = new QChart();

	//添加曲线到chart中
	ecgWaveLineChart->addSeries(ecgSeries);

	//设置坐标轴显示范围
	axisY_ECG->setRange(-350, 1200);
	axisX_ECG->setRange(0, 600);
	axisX_ECG->setTickCount(30);//横坐标30个数据点
	axisY_ECG->setTickCount(10);//纵坐标分为10块

	//设置坐标轴的颜色,粗细和设置网格显示
	axisX_ECG->setGridLinePen(QPen(Qt::red, 1, Qt::DashDotDotLine, Qt::SquareCap, Qt::RoundJoin)); //网格样式
	axisY_ECG->setGridLinePen(QPen(Qt::red, 1, Qt::DashDotDotLine, Qt::SquareCap, Qt::RoundJoin));

	axisX_ECG->setLinePen(QPen(Qt::red, 1, Qt::DashDotDotLine, Qt::SquareCap, Qt::RoundJoin));//坐标轴样式
	axisY_ECG->setLinePen(QPen(Qt::red, 1, Qt::DashDotDotLine, Qt::SquareCap, Qt::RoundJoin));

	axisY_ECG->setGridLineVisible(true);//显示线框
	axisX_ECG->setGridLineVisible(true);

	axisX_ECG->setLabelsVisible(false);//不显示label具体数值
	axisY_ECG->setLabelsVisible(false);

	//把坐标轴添加到chart中,第二个参数是设置坐标轴的位置,
	//只有四个选项,下方:Qt::AlignBottom,左边:Qt::AlignLeft,右边:Qt::AlignRight,上方:Qt::AlignTop
	ecgWaveLineChart->addAxis(axisX_ECG, Qt::AlignBottom);
	ecgWaveLineChart->addAxis(axisY_ECG, Qt::AlignLeft);

	//把曲线关联到坐标轴
	ecgSeries->attachAxis(axisX_ECG);
	ecgSeries->attachAxis(axisY_ECG);
	ecgSeries->setColor(QColor(Qt::black));//设置线的颜色
	//ecgSeries->setUseOpenGL(true);//openGL加速  在我的电脑上如果采用加速,绘制速度反倒会变慢
	setLineChartMargins(ecgWaveLineChart, 2);//设置折线图边距

	ecgWaveLineChart->legend()->hide();//不显示注释
	ui->ecgWaveLineChart->setChart(ecgWaveLineChart);//这里就可以把我们设置好的QrChart与QChartView进行绑定

}

}

这样,折线图的样式就设置好了:
QtCharts绘制动态心电图[1]——初步应用_第7张图片

心电图动态绘制主要代码

开启定时器并绑定定时槽函数

因为我的心电传感器的数据大概是8ms一个点,所以这里我使用定时器,每8ms进行一次任务:绘制一个新的点,8ms的时候,定时器会触发timeout信号,然后我们可以自定义每次定时器触发执行的任务oneTimeOutAction

void DynamicECG::onShowPushButtonClick()
{
	originList.clear();
	QString origin = ui->inputTextEdit->toPlainText();
	originList = origin.split(",");
	originListSize = originList.count();
	qDebug() << QString("数据大小%1").arg(originListSize);
	
	ecgWaveDrawTimer = new QTimer(this);//定时任务
	connect(ecgWaveDrawTimer, SIGNAL(timeout()), this, SLOT(oneTimeOutAction()));
	ecgWaveDrawTimer->start(8);//8ms执行一次

}

下方是oneTimeOutAction具体执行的函数

void DynamicECG::oneTimeOutAction() {
	//这里主要是实验用,当文本框数据绘制完毕后就停止绘制,在实际中可以没有这一行代码
	if (originListIndex >= originListSize)
	{
		ecgWaveDrawTimer->stop();
	}
	else {
		qint16 tempInt16 = originList.at(originListIndex).toInt();
		//qDebug() << QString("数据为:%1").arg(tempInt16);
		drawEcgWave(originListIndex, tempInt16);
		originListIndex++;
	}


}

波形绘制函数

绘制波形图的函数,主要是利用pointF的向量值赋值给series,然后通知series整体进行更改

//注意axis_x的输入,不要超过int的上限
void DynamicECG::drawEcgWave(int axis_x, qint16 data) {
	int timesCounts = axis_x / 600;//查看数据是否超过了600
	if (timesCounts > 0)//如果第一次界面绘制结束,之后存在了600个点
	{
		axis_x = axis_x - timesCounts * 600;
		ecgPointBuffer[axis_x].setY(data);//更改已有点的Y值
	
	}
	else//如果是第一次界面
	{
		ecgPointBuffer.append(QPointF(axis_x, data));
	}
	ecgSeries->replace(ecgPointBuffer);
}

其实写到这里,已经发现了一些问题了,比如定时器的频繁调用会造成系统响应变慢,以及很不方便控制绘制速度,有可能会出现延迟越来越大的现象,但是这个案例的确可以作为一个初步的使用,我后面的实现也是在这个的基础上一步步走过来的。

程序相关说明

运行程序,只需复制心电波形数据.csv中的内容,在下方的文本框中粘贴(其实可以写一个读取CSV文件数据的函数,这里为了方便就采用文本框的方式其实主要是偷懒),然后点击显示曲线即可实现波形的动态显示
QtCharts绘制动态心电图[1]——初步应用_第8张图片

程序及心电数据下载连接

说明:程序提供的下载(本程序是利用VS2017+Qt 5.11.2进行编写,建议用相同环境打开,不同的Qt版本可能会导致编译不成功,最近时间挺紧张,后面有时间可能再考虑转换成Qt版本)

我发现CSDN真的有趣,积分怎么越变越高。。。我还改不了需要积分,如果需要程序就留言邮箱吧 我有空发给你们。

写在最后

这一节已经实现了动态心电图,但是针对实时的心电数据,该程序还是需要做出一定的修改,下一章将会讲解动态曲线和数据的环形队列,才能真正实现数据的接收和实时绘制。
快速跳转链接:《QtCharts绘制动态心电图[2]——利用队列进行实时绘制》

你可能感兴趣的:(QT)