qwt官方例子-CurveDome

从效果展示,元素分析,代码分析来逐步说明qwt的使用方式。

本教程需要结合qwt的Class List来学习。

Qwt Class List: Qwt Class List:

项目源码:源码下载

效果展示

元素分析

元素分析中,将会说明本项目展示效果中的各个元素,方便小伙伴们学习并且灵活应用。

  • 多种曲线类型:
  • 绘制多条曲线
  • 使用QRect添加曲线说明文字
  • QPainter的一些简单使用

代码分析

从这个实例开始,实例代码已经逐渐开始多了,不再适合整体粘贴后分析,因此采用代码片段的方式进行,一般会从Qt的mian函数开始,通过函数或者类来进行分析。

主函数

#include <qwt_scale_map.h>
#include <qwt_plot_curve.h>
#include <qwt_symbol.h>
#include <qwt_math.h>
#include <qcolor.h>
#include <qpainter.h>
#include <qapplication.h>
#include <qfrfame.h>int main ( int argc, char **argv )
{QApplication a( argc, argv );MainWin w;w.resize( 300, 600 );w.show();return a.exec();
}

主函数比较简单,就是调用了一个类Mainwin的对象w,我们的重点要放在类Mainwin的实现上面。注意,这也是一般的我们使用Qwt的方式,将我们需要绘制的图写到一个类里面,编写好功能和接口函数,然后再主函数或者其他类中调用。

MainWin类-h文件

//   Array Sizes
const int Size = 27;  //全局变量  每条曲线上面点的个数
const int CurvCnt = 6;  //全局变量,曲线个数//   Arrays holding the values
double xval[Size];  //double类型的数组    备注:在C++中不推荐这么使用,推荐使用标准模板类库
double yval[Size];  //double类型的数组
QwtScaleMap xMap;   //Info1
QwtScaleMap yMap;class MainWin : public QFrame  //MainWin类继承自QFrame.  备注:QwtPlot其实也是继承自QFrame的
{public:MainWin();  //构造函数protected:virtual void paintEvent( QPaintEvent * );  //Qt的绘图事件void drawContents( QPainter *p );   //绘画函数private:void shiftDown( QRect &rect, int offset ) const;  //偏移函数,用来实现不同图形放置在不同位置QwtPlotCurve d_curves[CurvCnt];  //画布中的曲线数组,每个元素都是用来画一条曲线
};

Info1

QwtScaleMap xMap;
QwtScaleMap yMap;

参考文档:QwtScaleMap Class

QwtScaleMap是一个比例尺类,可以提供一个逻辑区域到实际区域的坐标转换。所谓逻辑区域,就是真正的数据的区域,比如绘图数据的Y轴范围是[-1,1],那么数据的Y轴坐标的范围就是[-1,1];所谓实际区域,意思是绘图区域,不管数据本身的数据范围是多大,而是按照绘图去也的大小,进行整体的缩放。

在本例中,是将数据生成的曲线都成比例投影到一个QRect中,关键代码是:

// 设置比例刻度(逻辑区域)
xMap.setScaleInterval( -0.5, 10.5 );
yMap.setScaleInterval( -1.1, 1.1 );
//设置绘图区域
QRect r = contentsRect();
//设置绘图区域
xMap.setPaintInterval( r.left(), r.right() );
yMap.setPaintInterval( r.top(), r.bottom() );painter->setRenderHint( QPainter::Antialiasing,d_curves[i].testRenderHint( QwtPlotItem::RenderAntialiased ) );
d_curves[i].draw( painter, xMap, yMap, r );

MainWin类-cpp文件

我们主要来分析MainWin类的实现。

先来看构造函数。

----------
MainWin::MainWin()
{int i;//设置比例尺的逻辑范围,后面绘图时要使用xMap.setScaleInterval( -0.5, 10.5 );  //设置曲线的逻辑范围,x轴范围是[-0.5,10.5]yMap.setScaleInterval( -1.1, 1.1 );   //设置曲线的逻辑范围,y轴范围是[-1.1,1.1]//  Frame stylesetFrameStyle( QFrame::Box | QFrame::Raised ); //Info2setLineWidth( 2 );   setMidLineWidth( 3 );// Calculate values  //计算绘制曲线用的点,每条曲线的点的坐标在逻辑上都是一样的for( i = 0; i < Size; i++ ){xval[i] = double( i ) * 10.0 / double( Size - 1 );yval[i] = qSin( xval[i] ) * qCos( 2.0 * xval[i] );}//  define curve stylesi = 0;//设置第一条曲线的样式,这里几段代码大同小异,只讲解第一段,其他几段类同//Info3//第一条d_curves[i].setSymbol( new QwtSymbol( QwtSymbol::Cross, Qt::NoBrush,QPen( Qt::black ), QSize( 5, 5 ) ) );  d_curves[i].setPen( Qt::darkGreen );d_curves[i].setStyle( QwtPlotCurve::Lines );d_curves[i].setCurveAttribute( QwtPlotCurve::Fitted );i++;//第二条d_curves[i].setSymbol( new QwtSymbol( QwtSymbol::Ellipse, Qt::yellow,QPen( Qt::blue ), QSize( 5, 5 ) ) );d_curves[i].setPen( Qt::red );d_curves[i].setStyle( QwtPlotCurve::Sticks );i++;//第三条d_curves[i].setPen( Qt::darkBlue );   //这条曲线对比第一条曲线,没有插值/平滑处理d_curves[i].setStyle( QwtPlotCurve::Lines );i++;//第四条d_curves[i].setPen( Qt::darkBlue );d_curves[i].setStyle( QwtPlotCurve::Lines );d_curves[i].setRenderHint( QwtPlotItem::RenderAntialiased );  //对比第三条曲线,进行了去锯齿处理i++;//第五条d_curves[i].setPen( Qt::darkCyan );d_curves[i].setStyle( QwtPlotCurve::Steps );i++;//第六条d_curves[i].setSymbol( new QwtSymbol( QwtSymbol::XCross, Qt::NoBrush,QPen( Qt::darkMagenta ), QSize( 5, 5 ) ) );d_curves[i].setStyle( QwtPlotCurve::NoCurve );i++;// attach datafor( i = 0; i < CurvCnt; i++ )d_curves[i].setRawSamples( xval, yval, Size );  //Info4
}----------
//Qt的绘画事件,当QWidget进行show,updata和repaint或者调整窗口大小时就会进行重绘
void MainWin::paintEvent( QPaintEvent *event )
{QFrame::paintEvent( event );QPainter painter( this );  //定义画笔painter.setClipRect( contentsRect() );  //设置一个矩形的剪裁区域drawContents( &painter );  //将画笔的指针传出到drawContents中进行绘画
}
----------
//REDRAW CONTENTS重绘内容
void MainWin::drawContents( QPainter *painter )
{int deltay, i;QRect r = contentsRect();  //创建一个矩阵deltay = r.height() / CurvCnt - 1;  //计算划分成6个Rect后的高度r.setHeight( deltay );  //重新设置矩阵的高度//  draw curvesfor ( i = 0; i < CurvCnt; i++ ){xMap.setPaintInterval( r.left(), r.right() );  //使用Rect来设置绘图区域yMap.setPaintInterval( r.top(), r.bottom() );painter->setRenderHint( QPainter::Antialiasing,d_curves[i].testRenderHint( QwtPlotItem::RenderAntialiased ) );  //根据曲线是否反锯齿来设置Painter是否反锯齿d_curves[i].draw( painter, xMap, yMap, r );  //使用设置的画笔、映射比例和矩阵来绘画曲线shiftDown( r, deltay );  //设置矩形位置在整个QWidget中的偏移}// draw titlesr = contentsRect();     // reset r,重新初始化一个Rectpainter->setFont( QFont( "Helvetica", 8 ) );const int alignment = Qt::AlignTop | Qt::AlignHCenter;  //设置矩阵中的内容的布局是垂直方向靠山和垂直方向剧中painter->setPen( Qt::black );  //设置画笔的颜色painter->drawText( 0, r.top(), r.width(), painter->fontMetrics().height(),alignment, "Style: Line/Fitted, Symbol: Cross" );  //Info5shiftDown( r, deltay );painter->drawText( 0, r.top(), r.width(), painter->fontMetrics().height(),alignment, "Style: Sticks, Symbol: Ellipse" );shiftDown( r, deltay );painter->drawText( 0 , r.top(), r.width(), painter->fontMetrics().height(),alignment, "Style: Lines, Symbol: None" );shiftDown( r, deltay );painter->drawText( 0 , r.top(), r.width(), painter->fontMetrics().height(),alignment, "Style: Lines, Symbol: None, Antialiased" );shiftDown( r, deltay );painter->drawText( 0, r.top(), r.width(), painter->fontMetrics().height(),alignment, "Style: Steps, Symbol: None" );shiftDown( r, deltay );painter->drawText( 0, r.top(), r.width(), painter->fontMetrics().height(),alignment, "Style: NoCurve, Symbol: XCross" );
}
----------
// 矩形在Y方向上的偏移
void MainWin::shiftDown( QRect &rect, int offset ) const
{rect.translate( 0, offset );
}

Info2

setFrameStyle( QFrame::Box | QFrame::Raised );
setLineWidth( 2 );   //设置外线宽度
setMidLineWidth( 3 ); //设置中线宽度

这里是```QFrame``的属性设置,可参考博客,博客中虽然是PyQt,但是不影响理解。

注意:这里设置的线宽是引擎绘制QFrame的线宽,跟咱们要绘制的曲线没有关系。

Info3

d_curves[i].setSymbol( new QwtSymbol( QwtSymbol::Cross, Qt::NoBrush,QPen( Qt::black ), QSize( 5, 5 ) ) );
d_curves[i].setPen( Qt::darkGreen );
d_curves[i].setStyle( QwtPlotCurve::Lines );
d_curves[i].setCurveAttribute( QwtPlotCurve::Fitted );i++;

第一行code是创建在曲线上面的符号Symbol,相关参数的意义在博客中有介绍,这里不再赘述;

第二行code是设置显示的画笔颜色为darkGreen;相关颜色很多,枚举如下:

enum GlobalColor {color0,color1, black,white,darkGray,gray,lightGray,red,green,blue,cyan,magenta,yellow,darkRed,darkGreen,darkBlue,darkCyan,darkMagenta,darkYellow,transparent};

第三行code是设置曲线的类型,相关的枚举为:

    enum CurveStyle{/*!Don't draw a curve. Note: This doesn't affect the symbols.不画曲线,但是不影响符号绘制*/NoCurve = -1,/*!Connect the points with straight lines. The lines mightbe interpolated depending on the 'Fitted' attribute. Curvefitting can be configured using setCurveFitter().使用直接连接各个点*/Lines,/*!Draw vertical or horizontal sticks ( depending on theorientation() ) from a baseline which is defined by setBaseline().在每个点上绘制竖直或水平的小棍棍*/Sticks,/*!Connect the points with a step function. The step functionis drawn from the left to the right or vice versa,depending on the QwtPlotCurve::Inverted attribute.在点上绘制阶梯*/Steps,/*!Draw dots at the locations of the data points. Note:This is different from a dotted line (see setPen()), and fasteras a curve in QwtPlotCurve::NoStyle style and a symbolpainting a point.在数据点上绘制点*/Dots,/*!Styles >= QwtPlotCurve::UserCurve are reserved for derivedclasses of QwtPlotCurve that overload drawCurve() withadditional application specific curve types.自定义曲线*/UserCurve = 100};

第四行code作用是在绘画曲线之前,对曲线进行插值/平滑处理。可以对比第一条曲线和第三条曲线,看看不同的效果。

备注:插值处理和去锯齿处理都是要额外消耗内存的。

Info4

d_curves[i].setRawSamples( xval, yval, Size );
--------
函数原型:
#ifndef QWT_NO_COMPATvoid setRawSamples( const double *xData, const double *yData, int size );void setSamples( const double *xData, const double *yData, int size );void setSamples( const QVector<double> &xData, const QVector<double> &yData );
#endifvoid setSamples( const QVector<QPointF> & );void setSamples( QwtSeriesData<QPointF> * );

setRawSamplessetSample的功能是一样的,区别是前者直接引用内存中的数据,而后者则会拷贝内内存数据。所以如果数据量比较大的话,最好使用前者,减少内存占用。

Info5

 painter->drawText( 0, r.top(), r.width(), painter->fontMetrics().height(),alignment, "Style: Line/Fitted, Symbol: Cross" );
---------
函数原型:
void drawText(const QRectF &r, int flags, const QString &text, QRectF *br = nullptr);
void drawText(const QRect &r, int flags, const QString &text, QRect *br = nullptr);
inline void drawText(int x, int y, int w, int h, int flags, const QString &text, QRect *br = nullptr);

比较好理解。其中

painter->fontMetrics()

是获取字体的度量。

总结

本教程内容较多,避开了继承使用QwtPlot类,而是直接从QFrame中进行曲线绘制,参杂了QPainter的一些使用,有一些难度,可以多过几遍,结合Qt帮助文档好好理解。

一般的绘制都是直接继承QwtPlot类的,所以这篇教程指导意义大于实践意义。

qwt官方例子-CurveDome相关推荐

  1. QWT官方例子--animation

    文章目录 一.运行效果 二.工程结构 三.代码分析 四.附加知识点 版本:qwt-6.1.3 一.运行效果 二.工程结构 本工程结构很简单,定义了继承自QwtPlot的Plot类,定义了一个继承自Qw ...

  2. 【Netty】入门Netty官方例子解析(二)Time Server

    本文承接上文<[Netty]入门Netty官方例子解析(一)写个 Discard Server> ,接下来讲解官网文档中Netty入门官方例子第二个例子 Time Server 原文这个章 ...

  3. Mule 官方例子研究

    Mule 官方例子研究 一.编译导入Mule自带的例子 1.准备 安装Mule.这里就不介绍mule的安装了,请参考<Mule安装部署手册>. 2. 编译Mule自带例子中的Hello例子 ...

  4. [FFmpeg] 编译官方例子

    官方例子地址 如果下载了源码,可在 ffmpeg-4.3.1/doc/examples/ 中查看 在Ubuntu 16.04 上,通过源码安装好 ffmpeg 后,运行官方例子 gcc -o demu ...

  5. 【TensorFlow】官方例子mnist_with_summaries.py在windows下运行tensorboard

    一.修改方案   TensorFlow官方例子mnist_with_summaries.py里面的主函数里面是按照linux的路径在写的,这在windows运行后生成的log文件路径会出现问题. 官方 ...

  6. leo-editor 关于 flutter 企业级路由 fluro 官方例子文学化编程分析

    fluro 是 flutter 企业级路由插件,在学习官方例子时有一些难度. fluro官方例子 下面是官方例子运行图 下面使用 leo-editor 对此例子进行文学化编程分析,按照从顶至底的顺序, ...

  7. VTK之MPR重建源码分析(VTK官方例子)

    VTK之MPR重建源码分析(VTK官方例子) 一,核心的控制十字轴旋转的代码 //----------------------------------------------------------- ...

  8. docx 图片预处理 Java_java使用poi给docx文档添加图片(官方例子)

    java使用poi给docx文档添加图片(官方例子) package org.apache.poi.xwpf.usermodel.examples; import java.io.FileInputS ...

  9. linux mule,Mule 官方例子研究(2)

    Mule 官方例子研究(2) 日期:2011-10-28 点击:169 来源: 未知 分享至: exchange-pattern=\"request-response\"> ...

最新文章

  1. python语言必背代码-好用到哭!请记住这20段Python代码
  2. hdu 1044 BFS(压缩图)+DFS
  3. “最害怕过周末”、“希望每天都干活”、“水电费又白交了”
  4. Django(part42)--限制IP请求次数
  5. linux apache jk,Linux下Apache+Tomcat+JK实现负载均衡和群集的完整过程
  6. python3.6+selenium_Testsuits测试套件
  7. 访问 JSON 对象的值
  8. Linux中使用tar打包解包查看的使用方法
  9. 【Hard 递归 动态规划 回文串15】LeetCode 730. Count Different Palindromic Subsequences
  10. XCL-Charts图表库中柱形图的同源风格切换介绍
  11. 谁偷偷删了你的微信?别慌!一篇Python学习教程帮你都揪出来
  12. php回滚实例_thinkphp 的事务回滚处理 和 原始PHP的事务回滚实例
  13. python用pandas读取txt_python Pandas 读取txt表格的实例
  14. docker的离线安装方法和网络源安装方法、内网环境linux脚本批量安装docker、安装docker-compose
  15. 快速养成一个好习惯?特别是小孩,培养一个习惯需要多长时间
  16. 通过阅读饥荒代码理解树人机制
  17. 那让人生生死死的「生态位」
  18. 计算机价格谈判议程,谈判议程
  19. 使用POI读取EXCEL模板并填充数据,上传至腾讯云储存桶
  20. 2022深圳杯AC题思路模型分析

热门文章

  1. java 阿里云视频点播上传
  2. 在人的一生,有些细微之事,本身毫无意义可言,却具有极大的重要性。事过境迁之后,回顾其因果关系,
  3. LWN:关于readahead的讨论!
  4. 技术管理者应有的 4 种基本思维模式
  5. 【沐风老师】3DMAX几何投影插件Geometry Projection使用详解
  6. Day33-Java面试系列(一)-Java基础(上)
  7. 机器人公敌过获奖没有_《机械公敌》观后感(学生作业)
  8. python及pygame雷霆战机游戏项目实战05 改进的碰撞
  9. MySQL中instr()函数用法
  10. 控制台程序源碼-飛行棋