Qwt开发笔记(二):Qwt基础框架介绍、折线图介绍、折线图Demo以及代码详解
前言
QWT开发笔记系列整理集合,这是目前使用最为广泛的Qt图表类(Qt的QWidget代码方向只有QtCharts,Qwt,QCustomPlot),使用多年,系统性的整理,本系列旨在系统解说并逐步更新其各种Demo示例
本片文章主要讲解折线图,借助折线图展现一个基础流程框架。
Demo
QwtPlot
简介
QwtPlot是一个用于绘制二维图形的小部件。画布上可以显示无限数量的绘图项目。绘图项目可以是曲线(QwtPlotCurve)、标记(QwtPlotMarker)、网格(QwtPrintGrid)或从QwtPlotItem派生的任何其他内容。一个绘图最多可以有四个轴,每个绘图项目都连接到一个x轴和一个y轴。轴上的比例可以显式设置(QwtScaleDiv),或使用算法(QwtScale Engine)根据绘图项计算,该算法可以为每个轴单独配置。
枚举
enum QwtPlot::LegendPosition:图例相对于画布的位置。
此枚举描述图表中启用的动画。
成员函数(列举常用的)
autoReplot():自动刷新
bool QwtPlot::autoReplot () const
如果设置了autoReplot选项,则为true。
axisAutoScale():自动缩放
bool QwtPlot::axisAutoScale(QwtAxisId axisId) const
如果启用了自动缩放,则为true。
axisFont():轴的刻度标签的字体
QFont QwtPlot::axisFont (QwtAxisId axisId) const
返回指定轴刻度的字体。
axisInterval():轴的当前间隔
QwtInterval QwtPlot::axisInterval(QwtAxisId axisId) const
返回指定轴的当前间隔。同axiscaleDiv(axisId)->interval()类似。
axisMaxMajor():轴的最大主刻度数
int QwtPlot::axisMaxMajor(QwtAxisId axisId) const
指定轴的最大主刻度数。
axisMaxMinor():轴的最大次刻度数
int QwtPlot::axisMaxMinor (QwtAxisId axisId) const
指定轴的最大次刻度数。
axisScaleDiv():轴的比例分割
const QwtScaleDiv & QwtPlot::axisScaleDiv(QwtAxisId axisId) const
返回指定轴的比例分割。
axiscaleDiv(axisId).lowerBound()和axiscaleDiv(axisId).upperBound()是轴比例的当前限制。
axisScaleDraw():轴的比例绘制
QwtScaleDraw * QwtPlot::axisScaleDraw(QwtAxisId axisId)
const QwtScaleDraw * QwtPlot::axisScaleDraw (QwtAxisId axisId) const
返回指定轴的比例绘制。
axisScaleEngine():轴的缩放引擎
QwtScaleEngine * QwtPlot::axisScaleEngine(QwtAxisId axisId)
const QwtScaleEngine * QwtPlot::axisScaleEngine(QwtAxisId axisId) const
返回轴的缩放引擎
axisStepSize():轴的步长
double QwtPlot::axisStepSize(QwtAxisId axisId) const
返回在setAxisScale中设置的步长参数。这不一定是当前比例的步长。
axisTitle():轴标题
QwtText QwtPlot::axisTitle(QwtAxisId axisId) const
axisWidget():缩放控件
QwtScaleWidget * QwtPlot::axisWidget(QwtAxisId axisId)
const QwtScaleWidget * QwtPlot::axisWidget(QwtAxisId axisId) const
指定轴的缩放控件,如果axisId无效,则为NULL。
canvasBackground():画布背景
QBrush QwtPlot::canvasBackground() const
绘图区域的背景画笔。
canvasMap():画布贴图
  QwtScaleMap QwtPlot::canvasMap(QwtAxisId axisId) const virtual
返回画布上轴的贴图。使用该贴图,像素坐标可以转换为绘图坐标,反之亦然。
drawCanvas():重绘画布
void QwtPlot::drawCanvas(QPainter * painter) virtual
重新绘制画布。drawCanvas调用同样用于打印的drawItems。喜欢添加单个绘图项的应用程序更好地重载drawItems()。
drawItems():重绘指定区域画布元素
void QwtPlot::drawItems(QPainter * painter,
const QRectF &canvasRect,
const QwtScaleMap
maps[QwtAxis::AxisPositions]) const virtual
通常canvasRect是绘图画布的contentsRect()。由于Qt中的错误,此矩形对于某些框架样式(例如QFrame::Box)可能是错误的,可能需要使用QWidget::setContentsMargins()手动修复边距
footer():页脚文本
QwtText QwtPlot::footer() const
页脚文本
footerLabel():页脚标签
QwtTextLabel * QwtPlot::footerLabel()
const QwtTextLabel * QwtPlot::footerLabel() const
页脚标签小部件。
getCanvasMarginsHint():获取画布边距
void QwtPlot::getCanvasMarginsHint(const QwtScaleMap maps[],
const QRectF & canvasRect,
double & left,
double & top,
double & right,
double & bottom) const virtual
计算画布边距。
insertLegend():插入图例
void QwtPlot::insertLegend(QwtAbstractLegend * legend,
QwtPlot::LegendPosition pos = wtPlot::RightLegend,
double ratio = -1.0)
插入图例。
如果位置图例是QwtPlot::LeftLegend或QwtPlot::RightLegend,则图例将从上到下组织在一列中。否则,图例项将放置在从左到右具有最佳列数的表中。
insertLegend()将把绘图小部件设置为图例的父项。图例将在绘图的析构函数中删除,或在插入另一个图例时删除。
未插入绘图小部件布局的图例需要连接到legendDataChanged()信号。调用updateLegend()将为初始更新启动此信号。当应用程序代码想要实现自己的布局时,也需要将绘图渲染到文档中。
invTransform():轴坐标转换
double QwtPlot::invTransform(QwtAxisId axisId, double pos ) const
将绘图区域中位置的x或y坐标转换为值。
isAxisValid():轴有效
bool QwtPlot::isAxisValid (QwtAxisId axisId) const
isAxisVisible():轴可见
bool isAxisVisible (QwtAxisId) const
replot():重绘
void QwtPlot::replot() virtual slot
QwtPlotGrid
简介
绘制坐标网格的类。
QwtPlotGrid类可用于绘制坐标网格。坐标轴网由主要和次要的垂直和水平轴网线组成。网格线的位置由X和Y比例划分确定,可以使用setXDiv()和setYDiv()指定。draw()成员在边界矩形内绘制网格。
成员函数(列举常用的)
enableX():启用或禁用垂直网格线。
void QwtPlotGrid::enableX(bool on)
enableY():启用或禁用水平网格线。
void QwtPlotGrid::enableY(bool on)
enableXMin():启用或禁用次要垂直网格线。
void QwtPlotGrid::enableXMin(bool on)
enableYMin():启用或禁用次要水平网格线。
void QwtPlotGrid::enableYMin(bool on)
majorPen():主要网格线的笔
const QPen & QwtPlotGrid::majorPen() const
minorPen():用于次要网格线的笔
const QPen & QwtPlotGrid::minorPen() const
QwtLegend
简介
图例小部件。
QwtLegend小部件是图例项的表格排列。图例项可以是任何类型的小部件,但通常它们都是QwtLegendLabel。
可设置只显示、显示可选择,显示可点击并抛出对应的信号。
使用时,直接new即可,没啥可说的。
QwtSymbol
简介
用于绘制符号的类,作用于实际数据点。
枚举
enum QwtSymbol::Style:绘制的数据点符号样式
成员函数(列举常用的)
setStyle() :设置点样式(配合上面枚举Style)
void QwtSymbol::setStyle (QwtSymbol::Style style)
setSize():设置点大小
void QwtSymbol::setSize(const QSize & size)
void QwtSymbol::setSize(int width, int height = -1)
指定符号的大小。
如果“h”参数被忽略或小于0,而“w”参数大于或等于0,则符号大小将设置为(w,w)。
QwtPlotCurve
(注意:本文只列Demo举用到的,下一篇文章将会着重讲解QwtPlotCurve类)
简介
表示一系列点的绘图项。
曲线是x-y平面中一系列点的表示。它支持不同的显示样式、插值(例如样条曲线)和符号。
指定曲线特性
创建曲线时,将配置为使用QwtPlotCurve::lines样式绘制黑色实线,而不使用符号。您可以通过调用setPen()、setStyle()和setSymbol()来更改此符号,使用QwtSymbol类来实现。
连接/分配数据
QwtPlotCurve使用QwtSeriesData对象获取其点,该对象为点的实际存储提供桥梁(如QAbstractItemModel)。
有几个从QwtSeriesData派生的便利类,它们也在内部存储点(如QStandardItemModel)。
QwtPlotCurve还提供了setSamples()的一些变体,它们从内部数组构建QwtSeriesData对象。
将曲线附加到绘图
将QwtPlotItem附加到QwtPlot。它将首先将QwtPlotItem从任何绘图中分离出来(如果需要)。如果传递了NULL参数,它将从它所附加的任何QwtPlot分离。(可以判断出,它只能附属一个绘图)
成员函数
setTitle():设置曲线的名称
void QwtPlotItem::setTitle(const QString & title)
void QwtPlotItem::setTitle(const QwtText & title)
setPen():设置曲线的画笔
void QwtPlotCurve::setPen(const QColor & color,
qreal width = 0.0,
Qt::PenStyle style = Qt::SolidLine)
void QwtPlotCurve::setPen(const QPen & pen)
指定画笔,宽度,线型等。
setXAxis():关联X轴
void QwtPlotItem::setXAxis(QwtAxisId axisId)
该项目将根据其坐标轴绘制。
setYAxis():关联Y轴
void QwtPlotItem::setYAxis(QwtAxisId axisId)
该项目将根据其坐标轴绘制。
setRenderHint():设置曲线渲染模式
void QwtGraphic::setRenderHint(RenderHint hint,
bool on = true);
只能设置QwtPlotItem::RenderAntialiased,然后参数为开启或者关闭。
setSamples():设置曲线数据
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()相反,此函数生成数据的“深度副本”。
attach():关联曲线到绘图
void QwtPlotItem::attach(QwtPlot * plot)
将项目附着到绘图。
此方法将QwtPlotItem附加到QwtPlot参数。它将首先将QwtPlotItem从任何绘图中分离出来(如果需要)。如果传递了NULL参数,它将从它所附加的任何QwtPlot分离。
Demo源码
LineChartWidget.h
#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
LineChartWidget.cpp
#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::xBottom, true);
}
// 设置y1坐标轴
{
_pQwtPlot->setAxisTitle(QwtPlot::yLeft, "y");
_pQwtPlot->setAxisAutoScale(QwtPlot::yLeft, true);
}
// 设置y2坐标轴
{
_pQwtPlot->setAxisTitle(QwtPlot::yRight, "y");
_pQwtPlot->setAxisVisible(QwtPlot::yRight, true);
_pQwtPlot->setAxisAutoScale(QwtPlot::yRight, true);
}
// 设置绘图区域网格
{
_pGrid = new QwtPlotGrid();
_pGrid->setMajorPen(Qt::gray, 1, Qt::SolidLine);
_pGrid->attach(_pQwtPlot);
}
// 设置图例
{
_pLegend = new QwtLegend();
_pLegend->setDefaultItemMode(QwtLegendData::ReadOnly);
_pQwtPlot->insertLegend(_pLegend);
}
// 设置曲线1
{
_pCurve1 = new QwtPlotCurve();
_pCurve1->setTitle("y1");
_pCurve1->setPen(Qt::blue, 1);
_pCurve1->setRenderHint(QwtPlotItem::RenderAntialiased, true);
// 关联轴
_pCurve1->setXAxis(QwtPlot::xBottom);
_pCurve1->setYAxis(QwtPlot::yLeft);
}
// 曲1符号对象
{
_pSymbol1 = new QwtSymbol(QwtSymbol::Ellipse);
_pSymbol1->setPen(Qt::red);
_pSymbol1->setBrush(Qt::red);
_pSymbol1->setSize(2);
_pCurve1->setSymbol(_pSymbol1);
}
// 曲线1数据
{
// 这是采用显示共享的方式
_pCurve1->setSamples(_vectorX1, _vectorY1);
// 将曲线添加到绘图
_pCurve1->attach(_pQwtPlot);
}
// 曲线2
{
_pCurve2 = new QwtPlotCurve();
_pCurve2->setTitle("y2");
_pCurve2->setPen(Qt::red, 1);
_pCurve2->setRenderHint(QwtPlotItem::RenderAntialiased, true);
// 关联轴
_pCurve2->setXAxis(QwtPlot::xBottom);
_pCurve2->setYAxis(QwtPlot::yRight);
}
// 曲线2数据
{
// 这是采用显示共享的方式
_pCurve2->setSamples(_vectorX2, _vectorY2);
// 将曲线添加到绘图
_pCurve2->attach(_pQwtPlot);
}
}
void LineChartWidget::slot_addDataTimeOut()
{
// 计算时间
double currentTime = QDateTime::currentDateTime().toMSecsSinceEpoch();
currentTime -= _startTime;
currentTime /= 1000;
// 添加曲线1数据
_vectorX1.append(currentTime);
_vectorY1.append(qrand() % 20 - 10);
// 添加曲线2数据
_vectorX2.append(currentTime);
_vectorY2.append(qrand() % 50);
// 数据置换(不知换数据进不去,显示共享无效?)
_pCurve1->setSamples(_vectorX1, _vectorY1);
_pCurve2->setSamples(_vectorX2, _vectorY2);
}
void LineChartWidget::resizeEvent(QResizeEvent *event)
{
if(_pQwtPlot)
{
_pQwtPlot->setGeometry(rect());
}
QWidget::resizeEvent(event);
}
void LineChartWidget::timerEvent(QTimerEvent *event)
{
// 计算时间
double currentTime = QDateTime::currentDateTime().toMSecsSinceEpoch();
currentTime -= _startTime;
currentTime /= 1000;
if(currentTime < 10.0)
{
_pQwtPlot->setAxisScale(QwtPlot::xBottom, 0, _rangeX, 1);
}else{
_pQwtPlot->setAxisScale(QwtPlot::xBottom, currentTime - _rangeX, currentTime, 1);
}
_pQwtPlot->replot();
}
QColor LineChartWidget::getBackgroundColor() const
{
return _backgroundColor;
}
void LineChartWidget::setBackgroundColor(const QColor &backgroundColor)
{
_backgroundColor = backgroundColor;
}
Demo工程模板v1.1.0
入坑
入坑一:使用显示setSample关联QVector失败
问题
显示共享理解为共用数据,但是数据不绘制到图。
尝试
查看曲线是否有更新数据到图的实现,是没有的。
直接设置可刷新数据
解决
直接setSample一次来解决。
Qwt开发笔记(二):Qwt基础框架介绍、折线图介绍、折线图Demo以及代码详解的更多相关文章
- Qt开发技术:QCharts(三)QCharts样条曲线图介绍、Demo以及代码详解
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- ArcGIS API for javascript开发笔记(五)——GP服务调用之GP模型的发布及使用详解
感谢一路走来默默陪伴和支持的你~~~ ----------------欢迎来访,拒绝转载---------------- 关于GP模型的制作请点我! 一.GP发布 ArcGIS Desktop可以作为 ...
- Linux及Arm-Linux程序开发笔记(零基础入门篇)
Linux及Arm-Linux程序开发笔记(零基础入门篇) 作者:一点一滴的Beer http://beer.cnblogs.com/ 本文地址:http://www.cnblogs.com/bee ...
- 【Linux开发】Linux及Arm-Linux程序开发笔记(零基础入门篇)
Linux及Arm-Linux程序开发笔记(零基础入门篇) 作者:一点一滴的Beer http://beer.cnblogs.com/ 本文地址:http://www.cnblogs.com/beer ...
- php后台开发(二)Laravel框架
php后台开发(二)Laravel框架 为了提高后台的开发效率,往往需要选择一套适合自己的开发框架,因此,选择了功能比较完善的Laravel框架,仔细学来,感觉和Python语言的框架Django非常 ...
- Django开发笔记二
Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.xadmin添加主题.修改标题页脚和收起左侧菜单 # ...
- Android基础夯实--重温动画(五)之属性动画 ObjectAnimator详解
只有一种真正的英雄主义 一.摘要 ObjectAnimator是ValueAnimator的子类,它和ValueAnimator一样,同样具有计算属性值的功能,但对比ValueAnimator,它会更 ...
- 基础 | batchnorm原理及代码详解
https://blog.csdn.net/qq_25737169/article/details/79048516 https://www.cnblogs.com/bonelee/p/8528722 ...
- 《手把手教你》系列技巧篇(二十九)-java+ selenium自动化测试- Actions的相关操作上篇(详解教程)
1.简介 有些测试场景或者事件,Selenium根本就没有直接提供方法去操作,而且也不可能把各种测试场景都全面覆盖提供方法去操作.比如:就像鼠标悬停,一般测试场景鼠标悬停分两种常见,一种是鼠标悬停在某 ...
- Spring Boot 2.x基础教程:进程内缓存的使用与Cache注解详解
随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决这一问题非常好的手段之一.Spring 3开始提供了强大的基于注解的缓 ...
随机推荐
- ES 7.13版本设置索引模板和索引生命周期管理
第一步:索引管理中查看都有哪些索引文件,然后添加索引模式(后面的日期用*表示) 第二步:索引生命周期管理 自带的有一个log,就使用这个,不用再新建了,根据需求修改里面的配置就行了 第三步:添加索引模 ...
- Prometheus监控Nginx
转载自:https://www.cnblogs.com/you-men/p/13173245.html CentOS7.3 prometheus-2.2.1.linux-amd64.tar.gz ng ...
- NOIP2003 普及组 洛谷P1045 麦森数 (快速幂+高精度)
有两个问题:求位数和求后500位的数. 求位数:最后减去1对答案的位数是不影响的,就是求2p的位数,直接有公式log10(2)*p+1; 求后500位的数:容易想到快速幂和高精度: 1 #includ ...
- RAID5 IO处理之replace代码详解
1 作用 从字面意思理解,replacement即是替换.我们知道硬盘都有一定的使用寿命,可以在硬盘失效之前通过该功能将就盘的数据迁移至新盘.因为replacement的流程是从旧盘中读出数据直接写入 ...
- java中list集合怎么判断是否为空
首先看下面代码 @RequestMapping("/getCatlist") public String getCatlist(HttpSession session,HttpSe ...
- uoj221【NOI2016】循环之美
前面部分比较简单,就是无脑化式子,简单点讲好了. 首先肯定在\((x,y)=1\)时才考虑这个分数,要求纯循环的话,不妨猜猜结论,就是y必须和K互质.所以答案是\(\sum_{i=1}^n \sum_ ...
- JSON parse error: Cannot deserialize value of type `java.lang.Integer` from Boolean value
问题原因所在:前端Vue传输的数据字段类型和后端实体类字段不一致. 我的实体类字段是int类型.前端传输的数据是布尔类型. 文章目录 1.后端方法 2.实体类字段 2.前端传输的数据 1.后端方法 @ ...
- 洛谷P5759题解
本文摘自本人洛谷博客,原文章地址:https://www.luogu.com.cn/blog/cjtb666anran/solution-p5759 \[这道题重在理解题意 \] 选手编号依次为: \ ...
- Python基础之函数:6、异常相关和生成器对象、yield用法、生成器表达式
目录 一.异常常见类型 1.类型错误 2.缩进错误 3.索引错误 4.语法错误 5.属性错误 6.key键错误 二.异常处理语法结构 1.基本语法结构 2.查看错误类型 3.针对不同类型所作措施 4. ...
- Python基础部分:8、for循环和range的使用
目录 一.while循环补充说明 1.死循环 2.嵌套及全局标志位 二.for...循环 1.for...循环特点 2.for...循环语法结构 三.range方法 1.什么是range 2.不同版本 ...