QWT開發筆記系列整理集合,這是目前使用最為廣泛的Qt圖表類(Qt的QWidget程式碼方向只有QtCharts,Qwt,QCustomPlot),使用多年,系統性的整理,本系列旨在系統解說並逐步更新其各種Demo範例
本片文章主要講解折線圖,藉助折線圖展現一個基礎流程框架。
QwtPlot是一個用於繪製二維圖形的小部件。畫布上可以顯示無限數量的繪圖專案。繪圖專案可以是曲線(QwtPlotCurve)、標記(QwtPlotMarker)、網格(QwtPrintGrid)或從QwtPlotItem派生的任何其他內容。一個繪圖最多可以有四個軸,每個繪圖專案都連線到一個x軸和一個y軸。軸上的比例可以顯式設定(QwtScaleDiv),或使用演演算法(QwtScale Engine)根據繪圖項計算,該演演算法可以為每個軸單獨設定。
此列舉描述圖表中啟用的動畫。
bool QwtPlot::autoReplot () const
如果設定了autoReplot選項,則為true。
bool QwtPlot::axisAutoScale(QwtAxisId axisId) const
如果啟用了自動縮放,則為true。
QFont QwtPlot::axisFont (QwtAxisId axisId) const
返回指定軸刻度的字型。
QwtInterval QwtPlot::axisInterval(QwtAxisId axisId) const
返回指定軸的當前間隔。同axiscaleDiv(axisId)->interval()類似。
int QwtPlot::axisMaxMajor(QwtAxisId axisId) const
指定軸的最大主刻度數。
int QwtPlot::axisMaxMinor (QwtAxisId axisId) const
指定軸的最大次刻度數。
const QwtScaleDiv & QwtPlot::axisScaleDiv(QwtAxisId axisId) const
返回指定軸的比例分割。
axiscaleDiv(axisId).lowerBound()和axiscaleDiv(axisId).upperBound()是軸比例的當前限制。
QwtScaleDraw * QwtPlot::axisScaleDraw(QwtAxisId axisId)
const QwtScaleDraw * QwtPlot::axisScaleDraw (QwtAxisId axisId) const
返回指定軸的比例繪製。
QwtScaleEngine * QwtPlot::axisScaleEngine(QwtAxisId axisId)
const QwtScaleEngine * QwtPlot::axisScaleEngine(QwtAxisId axisId) const
返回軸的縮放引擎
double QwtPlot::axisStepSize(QwtAxisId axisId) const
返回在setAxisScale中設定的步長引數。這不一定是當前比例的步長。
QwtText QwtPlot::axisTitle(QwtAxisId axisId) const
QwtScaleWidget * QwtPlot::axisWidget(QwtAxisId axisId)
const QwtScaleWidget * QwtPlot::axisWidget(QwtAxisId axisId) const
指定軸的縮放控制元件,如果axisId無效,則為NULL。
QBrush QwtPlot::canvasBackground() const
繪圖區域的背景畫筆。
  QwtScaleMap QwtPlot::canvasMap(QwtAxisId axisId) const virtual
返回畫布上軸的貼圖。使用該貼圖,畫素座標可以轉換為繪圖座標,反之亦然。
void QwtPlot::drawCanvas(QPainter * painter) virtual
重新繪製畫布。drawCanvas呼叫同樣用於列印的drawItems。喜歡新增單個繪圖項的應用程式更好地過載drawItems()。
void QwtPlot::drawItems(QPainter * painter,
const QRectF &canvasRect,
const QwtScaleMap
maps[QwtAxis::AxisPositions]) const virtual
通常canvasRect是繪圖畫布的contentsRect()。由於Qt中的錯誤,此矩形對於某些框架樣式(例如QFrame::Box)可能是錯誤的,可能需要使用QWidget::setContentsMargins()手動修復邊距
QwtText QwtPlot::footer() const
頁尾文字
QwtTextLabel * QwtPlot::footerLabel()
const QwtTextLabel * QwtPlot::footerLabel() const
頁尾標籤小部件。
void QwtPlot::getCanvasMarginsHint(const QwtScaleMap maps[],
const QRectF & canvasRect,
double & left,
double & top,
double & right,
double & bottom) const virtual
計算畫布邊距。
void QwtPlot::insertLegend(QwtAbstractLegend * legend,
QwtPlot::LegendPosition pos = wtPlot::RightLegend,
double ratio = -1.0)
插入圖例。
如果位置圖例是QwtPlot::LeftLegend或QwtPlot::RightLegend,則圖例將從上到下組織在一列中。否則,圖例項將放置在從左到右具有最佳列數的表中。
insertLegend()將把繪圖小部件設定為圖例的父項。圖例將在繪圖的解構函式中刪除,或在插入另一個圖例時刪除。
未插入繪圖小部件佈局的圖例需要連線到legendDataChanged()訊號。呼叫updateLegend()將為初始更新啟動此訊號。當應用程式程式碼想要實現自己的佈局時,也需要將繪圖渲染到檔案中。
double QwtPlot::invTransform(QwtAxisId axisId, double pos ) const
將繪圖區域中位置的x或y座標轉換為值。
bool QwtPlot::isAxisValid (QwtAxisId axisId) const
bool isAxisVisible (QwtAxisId) const
void QwtPlot::replot() virtual slot
繪製座標網格的類。
QwtPlotGrid類可用於繪製座標網格。座標軸網由主要和次要的垂直和水平軸網線組成。格線的位置由X和Y比例劃分確定,可以使用setXDiv()和setYDiv()指定。draw()成員在邊界矩形內繪製網格。
void QwtPlotGrid::enableX(bool on)
void QwtPlotGrid::enableY(bool on)
void QwtPlotGrid::enableXMin(bool on)
void QwtPlotGrid::enableYMin(bool on)
const QPen & QwtPlotGrid::majorPen() const
const QPen & QwtPlotGrid::minorPen() const
圖例小部件。
QwtLegend小部件是圖例項的表格排列。圖例項可以是任何型別的小部件,但通常它們都是QwtLegendLabel。
可設定只顯示、顯示可選擇,顯示可點選並丟擲對應的訊號。
使用時,直接new即可,沒啥可說的。
用於繪製符號的類,作用於實際資料點。
void QwtSymbol::setStyle (QwtSymbol::Style style)
void QwtSymbol::setSize(const QSize & size)
void QwtSymbol::setSize(int width, int height = -1)
指定符號的大小。
如果「h」引數被忽略或小於0,而「w」引數大於或等於0,則符號大小將設定為(w,w)。
(注意:本文只列Demo舉用到的,下一篇文章將會著重講解QwtPlotCurve類)
表示一系列點的繪圖項。
曲線是x-y平面中一系列點的表示。它支援不同的顯示樣式、插值(例如樣條曲線)和符號。
建立曲線時,將設定為使用QwtPlotCurve::lines樣式繪製黑色實線,而不使用符號。您可以通過呼叫setPen()、setStyle()和setSymbol()來更改此符號,使用QwtSymbol類來實現。
QwtPlotCurve使用QwtSeriesData物件獲取其點,該物件為點的實際儲存提供橋樑(如QAbstractItemModel)。
有幾個從QwtSeriesData派生的便利類,它們也在內部儲存點(如QStandardItemModel)。
QwtPlotCurve還提供了setSamples()的一些變體,它們從內部陣列構建QwtSeriesData物件。
將QwtPlotItem附加到QwtPlot。它將首先將QwtPlotItem從任何繪圖中分離出來(如果需要)。如果傳遞了NULL引數,它將從它所附加的任何QwtPlot分離。(可以判斷出,它只能附屬一個繪圖)
void QwtPlotItem::setTitle(const QString & title)
void QwtPlotItem::setTitle(const QwtText & title)
void QwtPlotCurve::setPen(const QColor & color,
qreal width = 0.0,
Qt::PenStyle style = Qt::SolidLine)
void QwtPlotCurve::setPen(const QPen & pen)
指定畫筆,寬度,線型等。
void QwtPlotItem::setXAxis(QwtAxisId axisId)
該專案將根據其座標軸繪製。
void QwtPlotItem::setYAxis(QwtAxisId axisId)
該專案將根據其座標軸繪製。
void QwtGraphic::setRenderHint(RenderHint hint,
bool on = true);
只能設定QwtPlotItem::RenderAntialiased,然後引數為開啟或者關閉。
void QwtPlotCurve::setSamples(const QVector< double > & xData,
const QVector< double > & yData)
使用x和y陣列初始化資料(顯式共用)。
void QwtPlotCurve::setSamples(const double * xData,
const double * yData,
int size)
通過從指定的記憶體塊複製x和y值來設定資料。與setRawSamples()相反,此函數生成資料的「深度副本」。
void QwtPlotItem::attach(QwtPlot * plot)
將專案附著到繪圖。
此方法將QwtPlotItem附加到QwtPlot引數。它將首先將QwtPlotItem從任何繪圖中分離出來(如果需要)。如果傳遞了NULL引數,它將從它所附加的任何QwtPlot分離。
#ifndef LINECHARTWIDGET_H
#define LINECHARTWIDGET_H
#include <QWidget>
#include <QTimer>
#include "qwt.h"
#include "qwt_plot.h"
#include "qwt_plot_grid.h"
#include "qwt_legend.h"
#include "qwt_plot_curve.h"
#include "qwt_symbol.h"
#include "qwt_spline_curve_fitter.h"
namespace Ui {
class LineChartWidget;
}
class LineChartWidget : public QWidget
{
Q_OBJECT
public:
explicit LineChartWidget(QWidget *parent = 0);
~LineChartWidget();
public:
QColor getBackgroundColor() const;
public:
void setBackgroundColor(const QColor &backgroundColor);
protected:
void initControl();
void initQwtPlot();
protected slots:
void slot_addDataTimeOut();
protected:
void resizeEvent(QResizeEvent *event);
void timerEvent(QTimerEvent *event);
private:
Ui::LineChartWidget *ui;
private:
int _timerId;
qint64 _startTime; // 啟動時間
private:
QColor _backgroundColor; // 背景顏色
private:
QwtPlot *_pQwtPlot; // qwt圖
QwtPlotGrid *_pGrid; // 虛線框
QwtLegend *_pLegend; // 圖例
QwtPlotCurve *_pCurve1; // 曲線1
QwtSymbol *_pSymbol1; // 曲線1點符號
QwtPlotCurve *_pCurve2; // 曲線2
QVector<double> _vectorX1; // 曲線1快取資料
QVector<double> _vectorY1; // 曲線1快取資料
QVector<double> _vectorX2; // 曲線2快取資料
QVector<double> _vectorY2; // 曲線2快取資料
double _rangeX; // 範圍
QTimer *_pTimerAddData; // 新增資料定時器
};
#endif // LINECHARTWIDGET_H
#include "LineChartWidget.h"
#include "ui_LineChartWidget.h"
#include <QDebug>
#include <QDateTime>
//#define LOG qDebug()<<__FILE__<<__LINE__
//#define LOG qDebug()<<__FILE__<<__LINE__<<__FUNCTION__
//#define LOG qDebug()<<__FILE__<<__LINE__<<QThread()::currentThread()
//#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd")
#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")
LineChartWidget::LineChartWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::LineChartWidget),
_pQwtPlot(0),
_pGrid(0),
_pLegend(0),
_pCurve1(0),
_pSymbol1(0),
_pCurve2(0),
_timerId(-1),
_pTimerAddData(0),
_rangeX(10)
{
ui->setupUi(this);
// 背景透明,在介面構架時,若為本視窗為其他視窗提升為本視窗時,
// 則再qss會在主視窗第一級新增frame_all,防止其他視窗提升本視窗而沖掉qss設定
// setWindowFlag(Qt::FramelessWindowHint);
// setAttribute(Qt::WA_TranslucentBackground, true);
initControl();
initQwtPlot();
_startTime = QDateTime::currentDateTime().toMSecsSinceEpoch();
_timerId = startTimer(16);
timerEvent(0);
}
LineChartWidget::~LineChartWidget()
{
delete ui;
}
void LineChartWidget::initControl()
{
_pTimerAddData = new QTimer(this);
connect(_pTimerAddData, SIGNAL(timeout()),
this, SLOT(slot_addDataTimeOut()));
_pTimerAddData->setInterval(1000);
_pTimerAddData->start();
}
void LineChartWidget::initQwtPlot()
{
_pQwtPlot = new QwtPlot(this);
// 設定背景色
_pQwtPlot->setCanvasBackground(QBrush(QColor(255, 255, 255)));
// 設定x1座標軸
{
_pQwtPlot->setAxisTitle(QwtPlot::xBottom, "x");
_pQwtPlot->setAxisAutoScale(QwtPlot