QChart雙Y軸笑窜,X軸設(shè)置時間軸
前言
工作上需要做一個雙Y軸的折線圖致燥,除了看QT的相關(guān)類的文檔,找到的資料不多怖侦,所以記錄下來篡悟。
準(zhǔn)備
首先,通過QT的幫助文檔了解下QChart匾寝、QSplineSeries(或者其他的Series類)搬葬、QValueAxis等類的描述,翻譯用的是有道的在線翻譯艳悔,自己再稍微修改一下不通順的地方急凰。
QChart
The QChart class manages the graphical representation of the chart's series, legends, and axes.
QChart類管理圖表中的線、圖例和軸的圖形表示猜年。
QChart is a QGraphicsWidget that you can show in a QGraphicsScene. It manages the graphical representation of different types of series and other chart related objects like legend and axes. To simply show a chart in a layout, the convenience class QChartView can be used instead of QChart. In addition, line, spline, area, and scatter series can be presented as polar charts by using the QPolarChart class.
QChart是一個可以在QGraphicsScene中顯示的QGraphicsWidget抡锈。它管理不同類型的系列和其他圖表相關(guān)對象(如圖例和軸)的圖形表示。要簡單地在布局中顯示圖表乔外,可以使用便利類QChartView代替QChart床三。此外,直線杨幼、平滑曲線撇簿、面積和散射圖可以通過QPolarChart類來表示為極坐標(biāo)圖。
QSplineSeries
The QSplineSeries class presents data as spline charts.
QSplineSeries類將數(shù)據(jù)表示為平滑曲線圖差购。
A spline series stores the data points and the segment control points needed by QPainterPath to draw a spline. The control points are automatically calculated when the data changes. The algorithm computes the points so that the normal spline can be drawn.
一個spline series存儲QPainterPath繪制平滑曲線所需的數(shù)據(jù)點和段控制點四瘫。當(dāng)數(shù)據(jù)發(fā)生變化時,控制點會自動計算欲逃。該算法對點進行計算找蜜,以便繪制平滑曲線。
QValueAxis
QValueAxis class adds values to a chart's axes.
QValueAxis類將值添加到圖表的軸中稳析。
A value axis can be set up to show an axis line with tick marks, grid lines, and shades. The values on the axis are drawn at the positions of tick marks.
可以設(shè)置一個值軸來顯示帶有標(biāo)記洗做、網(wǎng)格線和陰影的軸線弓叛。在軸上的值是在標(biāo)記的位置繪制的。
QDateTimeAxis
The QDateTimeAxis class adds dates and times to a chart's axis.
QDateTimeAxis類將日期和時間添加到圖表的軸中诚纸。
QDateTimeAxis can be set up to show an axis line with tick marks, grid lines, and shades. The labels can be configured by setting an appropriate DateTime format. QDateTimeAxis works correctly with dates from 4714 BCE to 287396 CE. For other limitiations related to QDateTime, see QDateTime documentation.
可以設(shè)置QDateTimeAxis來顯示帶有標(biāo)記標(biāo)記邪码、網(wǎng)格線和陰影的軸線∫澹可以通過設(shè)置適當(dāng)?shù)腄ateTime格式來配置軸線上顯示的值。QDateTimeAxis可以表示公元前4714年到公元287396年之間的時間奴潘。關(guān)于其他與QDateTime相關(guān)的信息旧烧,請參閱QDateTime文檔。
Note : QDateTimeAxis is disabled on platforms that define qreal as float.
注意 :在將qreal定義為float的平臺上禁用QDateTimeAxis画髓。
關(guān)于設(shè)置雙Y軸的比較重要的的函數(shù)是QChart的 addSeries掘剪,addAxis這兩個函數(shù),前者是添加線到QChart中奈虾,后者是添加坐標(biāo)軸到指定的位置夺谁。還有QSplineSeries的attachAxis函數(shù)。QT文檔中的描述如下:
void QChart::addSeries(QAbstractSeries *series)
Adds the series series to the chart and takes ownership of it.
將series添加到chart中肉微,并且chart獲得series的所有權(quán)匾鸥,即chart成為series的parent。
Note : A newly added series is not attached to any axes by default, not even those that might have been created for the chart using createDefaultAxes() before the series was added to the chart. If no axes are attached to the newly added series before the chart is shown, the series will get drawn as if it had axes with ranges that exactly fit the series to the plot area of the chart. This can be confusing if the same chart also displays other series that have properly attached axes, so always make sure you either call createDefaultAxes() after a series has been added or explicitly attach axes for the series.
注意 : 默認(rèn)情況下碉纳,新添加的series不會附加到任何軸上勿负,即使是那些在series添加到圖表之前使用chart的createDefaultAxes()函數(shù)為圖表創(chuàng)建的軸。如果在顯示圖表之前沒有附加任何坐標(biāo)軸到新添加的series上劳曹,那么這個數(shù)列就會被繪制出來奴愉,就好像它的坐標(biāo)軸的范圍恰好與這個series對應(yīng)于圖表的繪圖區(qū)域一樣。如果同一個圖表還顯示了其他附加了軸的series铁孵,那么這可能會繪制出令人困惑畫面锭硼,所以一定要確保在添加了series之后再調(diào)用createDefaultAxes(),或者顯式地為該series附加軸蜕劝。
void QChart::addAxis(QAbstractAxis *axis, Qt::Alignment alignment)
Adds the axis axis to the chart aligned as specified by alignment. The chart takes the ownership of the axis.
將坐標(biāo)軸添加到圖表中的指定的位置(左邊檀头,下方,右邊熙宇,上方)鳖擒。這個chart獲得坐標(biāo)軸的所有權(quán)。
bool QAbstractSeries::attachAxis(QAbstractAxis *axis)
Attaches the axis specified by axis to the series.
將指定的坐標(biāo)軸附加給series烫止。
Returns true if the axis was attached successfully, false otherwise.
如果成功蒋荚,返回true,否則馆蠕,返回false
Note : If multiple axes of the same orientation are attached to the same series, they will have the same minimum and maximum values.
注意 :如果同一系列上有多個相同方向的軸期升,它們的最小值和最大值是相同的惊奇。
編碼實現(xiàn)
接下來開始寫代碼,打開QT播赁,我的是QT5.11颂郎,新建工程,在.pro文件里增加
QT+=charts
在源文件里添加QChart的頭文件
#include <QtCharts>
#include <QtCharts/QSplineSeries>
在.cpp文件里增加命名空間
QT_CHARTS_USE_NAMESPACE
//或者 using namespace QtCharts;
然后在QT設(shè)計師里往窗口添加一個Graphics View容为,然后提升為QChartView乓序,
然后是編輯源文件,這里我就直接上代碼了坎背,代碼里寫有注釋替劈。
mainwindow.h文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtCharts>
#include <QtCharts/QSplineSeries>
#include <QDateTime>
?
?
namespaceUi{
classMainWindow;
}
?
classMainWindow:publicQMainWindow
{
Q_OBJECT
?
public:
explicitMainWindow(QWidget*parent=0);
~MainWindow();
?
/*menbers**************************************************************************************/
//聲明QChart的實例,QSplineSeries的實例
QChart*chart;
QSplineSeries*series1;
QSplineSeries*series2;
//聲明timer
QTimer*timer;
?
/*funcions **************************************************************************************/
//聲明劃線的函數(shù)和初始化QChart的函數(shù)
voiddrawLine();
voidinitChart();
?
publicslots:
/*slot function**********************************************************************************/
//聲明timer的槽函數(shù)
voidtimerDeal();
?
private:
Ui::MainWindow*ui;
};
?
#endif // MAINWINDOW_H
?mainwindow.cpp文件
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <math.h>
#include <QThread>
?
?
QT_CHARTS_USE_NAMESPACE
MainWindow::MainWindow(QWidget*parent) :
QMainWindow(parent),
ui(newUi::MainWindow)
{
ui->setupUi(this);
//初始化QChart
initChart();
?
//設(shè)置timer得滤,槽連接到
timer=newQTimer();
timer->setInterval(400);
connect(timer,SIGNAL(timeout()),this,SLOT(timerDeal()));
timer->start();
}
?
MainWindow::~MainWindow()
{
deleteui;
}
?
//實現(xiàn)QChart的初始化函數(shù)
voidMainWindow::initChart()
{
//初始化QChart的實例
chart=newQChart();
?
//初始化兩個QSplineSeries的實例
series1=newQSplineSeries();
series2=newQSplineSeries();
//設(shè)置兩條曲線的名稱
series1->setName("series1");
series2->setName("series2");
?
//把曲線添加到QChart的實例chart中
chart->addSeries(series1);
chart->addSeries(series2);
?
//聲明并初始化X軸陨献、兩個Y軸
QDateTimeAxis*axisX=newQDateTimeAxis();
// QValueAxis *axisX = new QValueAxis();
QValueAxis*axisY_1=newQValueAxis();
QValueAxis*axisY_2=newQValueAxis();
//設(shè)置坐標(biāo)軸顯示的范圍
axisX->setMin(QDateTime::currentDateTime().addSecs(-60*1));
axisX->setMax(QDateTime::currentDateTime().addSecs(0));
axisY_1->setMin(0);
axisY_1->setMax(18);
axisY_2->setMin(0);
axisY_2->setMax(18);
?
//設(shè)置坐標(biāo)軸上的格點
axisY_1->setTickCount(7);
axisY_2->setTickCount(11);
//設(shè)置坐標(biāo)軸顯示的名稱
axisX->setTitleText("X軸");
axisY_1->setTitleText("axisY_1-series1");
axisY_2->setTitleText("axisY_2-series2");
//設(shè)置坐標(biāo)軸的顏色,粗細(xì)懂更,設(shè)置網(wǎng)格不顯示
axisY_1->setLinePenColor(QColor(Qt::darkBlue));
axisY_1->setGridLineColor(QColor(Qt::darkBlue));
axisY_2->setLinePenColor(QColor(Qt::darkGreen));
axisY_2->setGridLineColor(QColor(Qt::darkGreen));
axisY_1->setGridLineVisible(false);
axisY_2->setGridLineVisible(false);
QPenpenY1(Qt::darkBlue,3,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin);
QPenpenY2(Qt::darkGreen,3,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin);
axisY_1->setLinePen(penY1);
axisY_2->setLinePen(penY2);
?
//把坐標(biāo)軸添加到chart中眨业,
//addAxis函數(shù)的第二個參數(shù)是設(shè)置坐標(biāo)軸的位置,
//只有四個選項沮协,下方:Qt::AlignBottom龄捡,左邊:Qt::AlignLeft,右邊:Qt::AlignRight慷暂,上方:Qt::AlignTop
chart->addAxis(axisX,Qt::AlignBottom);
chart->addAxis(axisY_1,Qt::AlignLeft);
chart->addAxis(axisY_2,Qt::AlignRight);
?
//把曲線關(guān)聯(lián)到坐標(biāo)軸
series1->attachAxis(axisX);
series1->attachAxis(axisY_1);
series2->attachAxis(axisX);
series2->attachAxis(axisY_2);
?
//把chart顯示到窗口上
ui->graphicsView->setChart(chart);
?
}
?
//實現(xiàn)畫線函數(shù)墅茉,動態(tài)更新
voidMainWindow::drawLine()
{
//每增加一個點改變X軸的范圍,實現(xiàn)曲線的動態(tài)更新效果
QDateTimebjtime=QDateTime::currentDateTime();
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
chart->axisX()->setMin(QDateTime::currentDateTime().addSecs(-60*1));
chart->axisX()->setMax(QDateTime::currentDateTime().addSecs(0));
?
//當(dāng)曲線上最早的點超出X軸的范圍時呜呐,剔除最早的點就斤,
if(series1->count()>119)
{
series1->removePoints(0,series1->count()-119);
}
if(series2->count()>119)
{
series2->removePoints(0,series2->count()-119);
}
?
intY1=qrand()%9;//隨機生成0到9的隨機數(shù)
intY2=9+qrand()%9;//隨機生成9到18的隨機數(shù)
//增加新的點到曲線末端
series1->append(bjtime.toMSecsSinceEpoch(),Y1);
series2->append(bjtime.toMSecsSinceEpoch(),Y2);
?
}
//實現(xiàn)timer的槽函數(shù)
voidMainWindow::timerDeal()
{
//定時畫曲線
drawLine();
}
?最終效果,曲線和X軸的范圍隨著時間實時更新蘑辑。
總結(jié)
了解了以后洋机,就覺得實現(xiàn)這個效果并不難,關(guān)鍵函數(shù)就那幾個洋魂。雖說不難绷旗,也算是解決了一個問題,獲得了成長副砍。
聲明
本文中的代碼均為本人所寫衔肢,本文亦是本人原創(chuàng),轉(zhuǎn)載請注明出處豁翎。