在Qt Charts发布之前, Qt比较著名两个画图插件是 qwt和Qcustom, 其中Qcustom较轻量,只需要在project 中包含qcustomplot.h 和 qcustomplot.cpp 几乎就可以使用。
相比Qcustom,qwt功能更为强大,但是它的安装十分麻烦,阻挡了很多人(包括我)的使用。
但是qwt只是对静态图表的表示非常不错,动态曲线性能并不突出。如果只是静态绘图,或者动态绘制的点并不多,继续用qwt甚至Qcustom完全没问题。
但是如果是新入手Qt绘图,用Qt charts显然是更好的选择,因为它在各方面都比前两者要好,并且也易于使用。
并且qml也支持charts,qml的渲染默认用GPU,成长性更好。
如果你在安装Qt的时候,选择了Qt charts部分,那么在Qt中使用charts 只需要 在 .pro文件中
QT += charts
并且在程序的开头加上一句 using namespace Qtcharts或者一个宏 QT_CHARTS_USE_NAMESPACE
进入主题: 动态实时折线图绘制
动态绘图,也就是说折线随着横坐标的增长而实时变化。
从这一秒和上一秒的变化看来,就是坐标轴不动,整个图像往前移了一个单位,然后在空出的最后一个位置增加了一个新的点。
想一下,只要你的显示器不能够随着横坐标的增长变宽,上面说的就是不得不做的事情。或者除非你不把最前面的那个点淘汰掉,但是那样的话,你的点只有增,没有删,随着时间的增长,点越来越多,曲线最后只会挤成一团,啥也看不清。
【多说一句,从相对的角度来说,既然可以把图像往前移一个单位,当然也可以坐标轴往后移一个单位,两者造成的结果当然是一样的。
Qt有一个函数scroll可以实现后者的功能,它有两个参数,可以设置每次x、y轴向右和向上滚动的距离。但是scroll函数绘制坐标轴感觉很奇怪……真的有一种在滚的感觉,看起来很难受,具体可以看Qt欢迎界面里面的一个示例子dynamicspline】
Qt charts中,可以主要一下几个类: QChart 和 QChartView,QChart是用什么画,差不多画笔的意思,QChartView是在什么上画,差不多画布的意思。
m_chartView = new QChartView(m_chart,this);//画布
m_chart = m_chartView->chart();//画笔
画笔绑在画布上,就新建了一个QChartView 和一个 QChart 指针。
类 Series 是用来添加数据的对象(可以理解为一个集合)。常见的 QLineSeries,折线类,画出来的先棱角更强,QSplineSeries,曲线类,画出来更平滑,QScatterSeries,点类,画出来是一个个单独的点。Qt文档对这些类都有很详细的说明,并配有图画。
类似于QChart 、QChartView、Series ,还有QValueAxis类(数值类型的坐标轴)等等,不再啰嗦,下面的代码里都有。并且有很详细的注释,想学的朋友一定仔细看一遍肯定能看明白。
ui->setupUi(this);
m_chart = new QChart();
m_chartView = new QChartView(m_chart,this);//画布
m_chart = m_chartView->chart();//画笔
m_chartView->setRubberBand(QChartView::NoRubberBand); //矩形缩放
m_chartView->setRenderHint(QPainter::Antialiasing); //设置抗锯齿
m_chartView->resize(600, 600); //画布大小
m_chartView->setContentsMargins(0,0,0,0);
m_chartView->show(); //显示
//设置x坐标轴
axisX = new QValueAxis;
axisX->setRange(0, 100); //范围
axisX->setLabelFormat("%d"); //图例的格式 %d为十进制显示
axisX->setGridLineVisible(true);//网格
axisX->setTickCount(10); //主要刻度
// axisX->setMinorTickCount(5);//小刻度
axisX->setTitleText("time/(s)");//标题
//设置y坐标轴
axisY = new QValueAxis;
axisY->setRange(0, 20);
axisY->setLabelFormat("%d");
axisY->setGridLineVisible(true);
axisY->setTickCount(10);//轴上有多少个标记数目
axisY->setMinorTickCount(5);//主要刻度之间有多少网格线
axisY->setTitleText("altitude/(%)");
m_chart->addAxis(axisX, Qt::AlignBottom); //将坐标轴加到chart上,居下
m_chart->addAxis(axisY, Qt::AlignLeft);//居左
//m_chart->setTitle("example of chart"); //设置图表标题
//m_chart->setAnimationOptions(QChart::SeriesAnimations); //曲线动画模式,不能启用这一项或是选择这个选项,这个会导致曲线闪烁
m_chart->legend()->setVisible(true); //设置图例可见
m_chart->legend()->setLayoutDirection(Qt::LeftToRight);
m_chart->legend()->setAlignment(Qt::AlignLeft);
//生成一小段数据列表用作绘图初始数据
QList<QPointF> mydata1;
for (int i = 0; i <100; i++)
{
mydata1.append(QPointF(i, 0.1*i));
}
addSeries(mydata1); //增加一条曲线,数据集为mydata1
connectMarkers(); //将曲线与图例连接起来,可以勾选进行显示与隐藏
m_chart->setAxisX(axisX, m_serieslist.first()); //将x和y坐标轴与第一条曲线连接
m_chart->setAxisY(axisY, m_serieslist.first());
timeId = startTimer(1000); //qobject中的函数,设置定时器时间间隔
线都是又一系列的点构成的,线是点的集合,容器里在包含一系列的线,用画笔绘制在画布上,这就是QChart
void Widget::addSeries(QList<QPointF> &data) //用于新增曲线
{
QSplineSeries *series = new QSplineSeries(this);//平滑曲线的集合
m_serieslist.append(series);//将曲线加到曲线列表中进行管理
series->setName(QString("line " + QString::number(m_serieslist.count()))); //设置曲线对应的名字,用于图例显示
series->append(data); //将数据加到曲线中
m_chart->addSeries(series);//将曲线增入chart中
axisX->setRange(0, series->count()); //坐标轴初始范围为图表中的数据数。 这个在绘制多条曲线中需注释
QPen splinePen ,linePen;
splinePen.setBrush(Qt::red);
splinePen.setColor(Qt::red);
series->setPen(splinePen);
QSplineSeries *lineSeries = new QSplineSeries(this);//折线类点的集合
lineSeries->setName(QStringLiteral("折线"));
QList<QPointF> lineData;
QPoint newPoint;
foreach (QPointF point, data) {
newPoint.setX(point.x() * 1.5);
newPoint.setY(point.y() * 1.5);
lineData.append(newPoint);
}
// lineSeries->append(0,0);
// lineSeries->append(10,10);
// lineSeries->append(15,15);
lineSeries->append(lineData);
linePen.setBrush(Qt::yellow);
lineSeries->setPen(linePen);
m_serieslist.append(lineSeries);
m_chart->addSeries(lineSeries);
}
的思想
利用定时器定时刷新不同的点,来实时绘制动态曲线
void Widget::timerEvent(QTimerEvent *event) //定时器事件的重构
{
if (event->timerId() == timeId)//定时器时间到,模拟数据填充
{
static QTime dataTime(QTime::currentTime());
long int eltime = dataTime.elapsed(); //上次start经过毫秒数
static int lastpointtime = 1;
int size = (eltime - lastpointtime);//数据个数
qDebug() << "size-->" << size;
foreach (QSplineSeries *splineSeries, m_serieslist) {
if (splineSeries->isVisible())
{
QVector<QPointF> olddata = splineSeries->pointsVector();
olddata.append(QPointF(lastpointtime +olddata.count(), lastpointtime*0.3));//填充数据--->>相当于每一分钟增加一点
axisX->setRange(0, lastpointtime + splineSeries->count());//设置x坐标轴
//后期需更改为一开始固定,只有当数据个数超出坐标轴范围时坐标轴开始扩展。
splineSeries->replace(olddata);
lastpointtime++;
}
}
}
}
效果图
源码请在链接在找到源码中
手机扫一扫
移动阅读更方便
你可能感兴趣的文章