QtCharts时间坐标轴,利用定时器动态绘制图

文章目录

  • 写在前面
  • 为什么要写这片文章
  • QtCharts折线图初始化设置
    • UI设置
    • 折线图初始化
    • 往Chart中添加数据的方法
  • 定时器与绘制
  • 其他
    • 设置坐标轴样式的函数,
    • 设置折线图边距
    • 下载
    • 相关

先放效果图
QtCharts时间坐标轴,利用定时器动态绘制图_第1张图片

写在前面

这片文章是之前文章思路上来的,之前的这篇文章是在项目初期,刚开始使用QtCharts时候写的,当时比较匆忙,没有太多时间编写一个Demo,代码也是从项目中抠出来的,难免会有不足之处,现在看起来有点晦涩,可能对大家的帮助不大,所以想进行一定修改,让大家能够更好的使用Qt自带的折线图,实现更多功能。
本来是想在之前的文章上进行修改,但是毕竟也是以前的一个印记。这次就在上那篇文章的基础上,试图让整个流程更加清楚,增加一些新内容,也会配上Demo的下载地址。

另外,本Demo的开发环境是VS2017社区版+Qt 5.11.2,QtChart的添加方式和使用Qt Creator略有不同。(本人觉得开发大一点的项目还是VS方便,所以就一直使用的VS进行开发)

为什么要写这片文章

QtCharts常用的时间轴有QValueAxisQDateTimeAxis,有时候我们需要绘制与时间相关的数据,如与日期相关的天气数据,或者是随分钟变化的传感器数据等,这样就会用到 QDateTimeAxis 坐标轴目前网上的一些例子,以及QT自带的例子,基本都是和日期相关的数据,没有找到坐标轴是分钟、秒的案例,踩了一些坑后,写下这篇文章,希望能够帮助到需要的人。

QtCharts折线图初始化设置

UI设置

记得在生成项目的时候勾选charts(安装Qt的时候记得也要安装这个组件),这样就能正常使用QtCharts,一路next就可以生成我们的项目了。
QtCharts时间坐标轴,利用定时器动态绘制图_第2张图片
我们要实现折线图需要利用QChartView,在QChartView中才可以添加QChart。
双击ui文件打开QtDesigner,我们会发现没有现成的QChartView控件。但是问题不大,QChartView是继承于GraphicsView的,所以我们可以通过Qt的一些操作,将GraphicsView变为我们要使用的QChartView
首先我们拖动一个GraphicsView到右边去,对着添加进去的控件右键,选择提升,然后在弹出窗口,进行下面的操作,确定后我们就可以得到一个QChartView了。

QtCharts时间坐标轴,利用定时器动态绘制图_第3张图片
可以看到,右边属性界面我们的graphicsView的类就变为了QChartView
QtCharts时间坐标轴,利用定时器动态绘制图_第4张图片
这个时候我们进行编译,是会报错的,大概就是下面这个样子
QtCharts时间坐标轴,利用定时器动态绘制图_第5张图片
需要在头文件中添加一个包含,就可以正常使用了
QtCharts时间坐标轴,利用定时器动态绘制图_第6张图片


折线图初始化

主要是初始化坐标轴和数据集,以及QChart对象。(我们这里既有左边的Y轴,又有右边的Y轴,如果只是想显示普通一条数据,只需要一个Y轴就可以了)

m_AxisX_Time = new QDateTimeAxis();//时间轴    
m_AxisY_Left = new QValueAxis();//左边Y轴    
m_AxisY_Right = new QValueAxis();//右边Y轴    
m_LeftSeries = new QLineSeries();//折线图数据集    
m_RightSeries = new QLineSeries();    
m_LineChart = new QChart();//chart对象

其中这个m_LineChart是要添加到我们QChartView中的具体对象,也是折线图的具体对象。
有了这些对象,我们需要对他们之间进行初始设置,添加他们之间的关系,让他们能够各司其职,共同工作。


首先就是把我们的数据集加入到我们的chart中

 //添加曲线到chart中    
 m_LineChart->addSeries(m_LeftSeries);    
 m_LineChart->addSeries(m_RightSeries);

然后我们对坐标轴进行一定的设置。时间轴设置区间需要用到QDateTime,QDateTime是一个年月日,时分秒的时间类,构造函数是由年月日的m_BaseData对象(QDate类)和m_BaseTime对象(QTime类)组成,但是因为我们想要显示时分秒或者分秒,所以调用下面一句话,我们可以只是显示分秒。

m_AxisX_Time->setFormat(“mm:ss”)

具体的代码如下

QDateTime temp_StartTime(m_BaseDate, m_BaseTime);//00:00    
QDateTime temp_EndTime(m_BaseDate, m_EndTime);//02:00
m_AxisX_Time->setTickCount(6);//分为六格    
m_AxisX_Time->setRange(temp_StartTime, temp_EndTime);//时间显示范围
//坐标轴显示方式: 分钟:秒    
m_AxisX_Time->setFormat("mm:ss");
//设置坐标轴显示范围    
m_AxisY_Left->setRange(-900, 2000);    
m_AxisY_Right->setRange(-900, 1500);
  • 这里有一个坑,QDateTime中,如果初始化输入QDateQTime时间不正确,那么理论上QDateTime也是错误的,但是系统是不会报错的,但会导致显示数据异常;
  • 比如QDate如果是(2000,0,1),不会提示错误,但是其实显示的数值会一直是错误的
  • 所以为了保证数据的正确性,这些容易出错的对象我们尽量用全局的const变量来提前定义,如m_BaseDate

然后我们把设置好的坐标添加到chart中,和添加进数据集的方法相似

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

最后将数据集和坐标轴绑定。每个数据集都需要绑定X轴-时间轴和对应的Y轴,如果想要添加多条折线图,原理也是一样的,只需要绑定X轴和对应的Y轴就可以了。

//把曲线关联到坐标轴    
m_LeftSeries->attachAxis(m_AxisX_Time);    
m_LeftSeries->attachAxis(m_AxisY_Left);    
m_RightSeries->attachAxis(m_AxisX_Time);    
m_RightSeries->attachAxis(m_AxisY_Right);

到这里,我们的chart就设置完毕了,我们将设置好的chart添加进我们的chartView中就可以了

ui.graphicsView->setChart(m_LineChart);

往Chart中添加数据的方法

想要往QtChart中添加数据,只需要往对应的数据集series中添加点,为了方便调用,这里写成了一个函数形式。

/** 
* 添添加一个点 
* */
void QtChartTimeAxis::addOnePointToChart(QLineSeries *targetSeries, int secondCount, int y_value) 
{    
QDateTime temp_AddTimePos(m_BaseDate, m_BaseTime.addSecs(secondCount));//通过addSecs增加秒数,更加安全    
targetSeries->append(temp_AddTimePos.toMSecsSinceEpoch(), y_value);
}

定时器与绘制

我们这里通过定时器,每一秒钟绘制一次数据点,这和我们期望的实际的工作方式是一致。

//初始化一个定时器    
m_DrawTimer = new QTimer(this);    
connect(m_DrawTimer, &QTimer::timeout, this, &QtChartTimeAxis::oneSecondAction);//槽函数,每次定时器达到指定时间就执行一次

开始定时器只需要执行下面这一行,括号内这个间隔单位是ms,可以按照自己的要求进行更改。

m_DrawTimer->start(1000);//1秒执行一次

然后在每秒响应的槽函数中,每一秒调用一次addOnePointToChart函数,

second_count++;
addOnePointToChart(m_LeftSeries, second_count, m_DataList[second_count].toInt());

其他

设置坐标轴样式的函数,

可以设置左右Y轴的颜色,名称,以及让曲线颜色和Y轴颜色一致。因为不是非常重要,就放在了最后

/** 
* 设置坐标轴样式 
* */
void QtChartTimeAxis::setAxisFormat(QValueAxis *axis, QXYSeries *lineSeries, QString titleString, QColor color)
{ 
axis->setTitleText(titleString); 
axis->setTitleFont(QFont("黑体", 8, QFont::Medium, false)); 
axis->setTitleBrush(color); 
axis->setLinePenColor(color); 
lineSeries->setPen(QPen(color, 0.6, Qt::SolidLine, Qt::SquareCap, Qt::RoundJoin));}

设置折线图边距

同样的,因为不是非常重要,就放在了最后。但是有时候可能会对边距有要求。

/** * 用于设置折线图边距 */ 
void QtChartTimeAxis::setLineChartMargins(QChart *chart, int margin) 
{ 
QMargins m_Margin; 
m_Margin.setLeft(margin); 
m_Margin.setBottom(margin); 
m_Margin.setRight(margin); 
m_Margin.setTop(margin); 
chart->setMargins(m_Margin); 
}

下载

下载 程序及数据下载连接

说明:程序提供的下载(本程序是利用VS2017+Qt 5.11.2进行编写,建议用相同环境打开)

相关

QtChart还是适合轻量级的应用,比如这个Demo是1s绘制一次,所以性能上没有一点问题,100ms也不会有什么问题,但是10ms的绘制间隙后,系统明显会卡顿了,这对系统执行的其他任务影响很大,这个时候就需要自定义的绘制模块了。

  • 这个Demo的扩展方向有很多,比如QtCharts绘制动态心电图[1]——初步应用
  • 还有进行优化后,根据传感器数据实时绘制心电图QtCharts绘制动态心电图[2]——利用队列进行实时绘制

你可能感兴趣的:(QT)