前言
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"