【1】实例代码

(1)代码目录结构(备注:QtCreator默认步骤新建工程)

(2)工程pro文件

  1. QT += core gui
  2.  
  3. greaterThan(QT_MAJOR_VERSION, ): QT += widgets
  4.  
  5. TARGET = painter
  6. TEMPLATE = app
  7.  
  8. SOURCES += main.cpp\
  9. mainwindow.cpp
  10.  
  11. HEADERS += mainwindow.h
  12.  
  13. FORMS += mainwindow.ui

(3)头文件

  1. #ifndef MAINWINDOW_H
  2. #define MAINWINDOW_H
  3.  
  4. #include <QtGui>
  5. #include <QPaintEvent>
  6. #include <QMainWindow>
  7.  
  8. #include <ctime>
  9. #include <cstdlib>
  10.  
  11. namespace Ui
  12. {
  13. class MainWindow;
  14. }
  15.  
  16. class MainWindow : public QMainWindow
  17. {
  18. Q_OBJECT
  19.  
  20. public:
  21. explicit MainWindow(QWidget *parent = );
  22. ~MainWindow();
  23.  
  24. void Paint();
  25.  
  26. public slots:
  27. void onRefresh();
  28. protected:
  29. void paintEvent(QPaintEvent *);
  30.  
  31. private:
  32. Ui::MainWindow *ui;
  33. QImage m_image;
  34. QPainter *m_painter;
  35. };
  36.  
  37. #endif // MAINWINDOW_H

(4)实现文件

  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3.  
  4. #define POINTSNUM 10
  5. #define LowerFactor 0.8
  6. #define UpperFactor 1.2
  7.  
  8. typedef struct Data
  9. {
  10. double scaleRange;
  11. double maxScale;
  12. double minScale;
  13. QVector<double> vecData;
  14.  
  15. Data() : scaleRange(0.0), maxScale(0.0), minScale(0.0)
  16. {}
  17. void init()
  18. {
  19. for (int i = ; i < POINTSNUM; ++i)
  20. {
  21. if (i % )
  22. vecData.append(rand() % - );
  23. else
  24. vecData.append(rand() % + );
  25. }
  26. double maxElement = *(std::max_element(vecData.begin(), vecData.end()));
  27. double minElement = *(std::min_element(vecData.begin(), vecData.end()));
  28. if (maxElement < )
  29. {
  30. maxScale = maxElement * LowerFactor;
  31. minScale = minElement * UpperFactor;
  32. }
  33. else if ( == maxElement)
  34. {
  35. maxScale = ;
  36. minScale = minElement * UpperFactor;
  37. }
  38. else if (maxElement > && minElement < )
  39. {
  40. maxScale = maxElement * UpperFactor;
  41. minScale = minElement * UpperFactor;
  42. }
  43. else if (minElement > )
  44. {
  45. maxScale = maxElement * UpperFactor;
  46. minScale = minElement * LowerFactor;
  47. }
  48.  
  49. scaleRange = maxScale - minScale;
  50. }
  51. void print()
  52. {
  53. for (int i = ; i < POINTSNUM; ++i)
  54. {
  55. qDebug () << i << "::" << vecData[i] << " ";
  56. }
  57. qDebug() << endl;
  58. }
  59. }DataInfo;
  60.  
  61. MainWindow::MainWindow(QWidget *parent)
  62. : QMainWindow(parent),
  63. ui(new Ui::MainWindow)
  64. {
  65. ui->setupUi(this);
  66. ui->mainToolBar->setVisible(true);
  67.  
  68. QAction *pAction = new QAction("refresh", this);
  69. ui->mainToolBar->addAction(pAction);
  70. connect(pAction, &QAction::triggered, this, &MainWindow::onRefresh);
  71.  
  72. resize(, ); // 窗体大小 宽度1000 高度730
  73.  
  74. m_image = QImage(, , QImage::Format_RGB32); // 画布的初始化大小设为,使用32位颜色
  75. QColor backColor = qRgb(, , ); // 画布初始化背景色使用白色
  76. m_image.fill(backColor); // 对画布进行填充
  77.  
  78. m_painter = new QPainter(&m_image);
  79. m_painter->setRenderHint(QPainter::Antialiasing, true); // 设置反锯齿模式
  80.  
  81. Paint();
  82. }
  83.  
  84. void MainWindow::onRefresh()
  85. {
  86. m_painter->fillRect(, , - , - , Qt::white);
  87. Paint();
  88. update();
  89. }
  90.  
  91. void MainWindow::Paint()
  92. {
  93. // 确定坐标轴起点坐标
  94. int pointx = , pointy = ;
  95.  
  96. // 确定坐标轴宽度和高度,上文已定义画布大小,宽高依此而定。
  97. int width = - pointx - ; // 宽度 = 画布宽度 - 坐标起点x - 右端间隙
  98. int height = - * ; // 高度 = 画布高度 - 上下端的间隙高度
  99.  
  100. // 绘制视图区域
  101. // 即外围的矩形(由左上角与右下角的两个点确定一个矩形)
  102. m_painter->drawRect(, , - , - );
  103.  
  104. // 绘制X、Y1、Y2轴
  105. QPointF xStartPoint(pointx, pointy);
  106. QPointF xEndPoint(width + pointx, pointy);
  107. m_painter->drawLine(xStartPoint, xEndPoint); // 坐标轴x宽度为width
  108.  
  109. QPointF y1StartPoint(pointx, pointy - height);
  110. QPointF y1EndPoint(pointx, pointy);
  111. m_painter->drawLine(y1StartPoint, y1EndPoint); // 坐标轴y1高度为height
  112.  
  113. QPointF y2StartPoint(pointx + width, pointy - height);
  114. QPointF y2EndPoint(pointx + width, pointy);
  115. m_painter->drawLine(y2StartPoint, y2EndPoint); // 坐标轴y2高度为height
  116.  
  117. // (2)获得数据并分析最大值与最小值
  118. DataInfo vectorX, vectorY1, vectorY2; // 数据储存在容器中,大小为POINTSNUM]
  119. // 模拟随机数据
  120. srand((int)time(NULL));
  121. vectorX.init();
  122. vectorY1.init();
  123. vectorY2.init();
  124.  
  125. vectorX.print();
  126. vectorY1.print();
  127. vectorY2.print();
  128.  
  129. double kx = (double)(width / vectorX.scaleRange); // x轴的系数
  130. double ky1 = (double)(height / vectorY1.scaleRange); // y1方向的比例系数
  131. double ky2 = (double)(height / vectorY2.scaleRange); // y2方向的比例系数
  132.  
  133. // (3)绘制点
  134. QPen penPointY1, penPointY2;
  135. penPointY1.setColor(Qt::blue);
  136. penPointY1.setWidth();
  137.  
  138. penPointY2.setColor(Qt::red);
  139. penPointY2.setWidth();
  140.  
  141. for (int i = ; i < POINTSNUM; ++i)
  142. {
  143. double dXStart = pointx + kx * (vectorX.vecData[i] - vectorX.minScale);
  144. m_painter->setPen(penPointY1); // 蓝色的笔,用于标记Y1各个点
  145. m_painter->drawPoint(dXStart, pointy - (vectorY1.vecData[i] - vectorY1.minScale) * ky1);
  146.  
  147. m_painter->setPen(penPointY2); // 红色的笔,用于标记Y2各个点
  148. m_painter->drawPoint(dXStart, pointy - (vectorY2.vecData[i] - vectorY2.minScale) * ky2);
  149. }
  150.  
  151. // (4) 绘制刻度线
  152. QPen penDegree;
  153. penDegree.setColor(Qt::black);
  154. penDegree.setWidth();
  155. m_painter->setPen(penDegree);
  156.  
  157. // x轴刻度线和值
  158. // x轴 第一个刻度值
  159. m_painter->drawText(pointx + , pointy + , QString::number(vectorX.minScale, 'f', ));
  160. for (int i = ; i < POINTSNUM - ; ++i) // 分成10份
  161. {
  162. // // 选取合适的坐标,绘制一段长度为4的直线,用于表示刻度
  163. // m_painter->drawLine(pointx + (i + 1) * width/10, pointy,
  164. // pointx + (i+1)*width/10, pointy + 4);
  165.  
  166. m_painter->drawText(pointx + (i+0.9) * width / POINTSNUM, pointy + , // 值的位置信息
  167. QString::number(vectorX.minScale + (i+) * (vectorX.scaleRange/POINTSNUM), 'f', ));
  168. }
  169. // x轴 最后一个刻度值
  170. m_painter->drawText(pointx + (POINTSNUM - + 0.8) * width / POINTSNUM, pointy + ,
  171. QString::number(vectorX.maxScale, 'f', ));
  172.  
  173. xStartPoint.setX(pointx);
  174. xStartPoint.setY(pointy + );
  175. xEndPoint.setX(pointx + width);
  176. xEndPoint.setY(pointy + );
  177. m_painter->drawLine(xStartPoint, xEndPoint);
  178.  
  179. m_painter->drawText(pointx + width/, pointy + , QString("X"));
  180.  
  181. // y1轴刻度线和值
  182. // y1轴 第一个刻度值
  183. m_painter->drawText(pointx - , pointy - , QString::number(vectorY1.minScale, 'f', ));
  184. for (int i = ; i < POINTSNUM - ; ++i)
  185. {
  186. // 代码较长,但是掌握基本原理即可。
  187. // 主要就是确定一个位置,然后画一条短短的直线表示刻度。
  188.  
  189. // m_painter->drawLine(pointx, pointy-(i+1)*height/10,
  190. // pointx-4, pointy-(i+1)*height/10);
  191.  
  192. m_painter->drawText(pointx - , pointy - (i+0.85) * height/POINTSNUM,
  193. QString::number(vectorY1.minScale + (i+) * (vectorY1.scaleRange/POINTSNUM), 'f', ));
  194. }
  195. // y1轴 最后一个刻度值
  196. m_painter->drawText(pointx - , pointy - (POINTSNUM - + 0.85) * height/POINTSNUM,
  197. QString::number(vectorY1.maxScale, 'f', ));
  198.  
  199. y1StartPoint.setX(pointx - );
  200. y1StartPoint.setY(pointy - height);
  201.  
  202. y1EndPoint.setX(pointx - );
  203. y1EndPoint.setY(pointy);
  204. m_painter->drawLine(y1StartPoint, y1EndPoint);
  205.  
  206. m_painter->drawText(pointx - , pointy - height/, QString("Y1"));
  207.  
  208. // y2轴刻度线和值
  209. // y2轴 第一个刻度值
  210. m_painter->drawText(pointx + width + , pointy - , QString::number(vectorY2.minScale, 'f', ));
  211. for (int i = ; i < POINTSNUM - ; ++i)
  212. {
  213. // m_painter->drawLine(pointx + width, pointy-(i+1)*height/10,
  214. // pointx + width + 4, pointy-(i+1)*height/10);
  215.  
  216. m_painter->drawText(pointx + width + , pointy - (i+0.85)*height/POINTSNUM,
  217. QString::number((vectorY2.minScale + (i+)*(vectorY2.scaleRange/POINTSNUM)), 'f' , ));
  218. }
  219. // Y2轴 最后一个刻度值
  220. m_painter->drawText(pointx + width + , pointy - (POINTSNUM - + 0.85)*height/POINTSNUM,
  221. QString::number(vectorY2.maxScale, 'f', ));
  222.  
  223. y2StartPoint.setX(pointx + width + );
  224. y2StartPoint.setY(pointy - height);
  225.  
  226. y2EndPoint.setX(pointx + width + );
  227. y2EndPoint.setY(pointy);
  228. m_painter->drawLine(y2StartPoint, y2EndPoint);
  229.  
  230. m_painter->drawText(pointx + width + , pointy - height/, QString("Y2"));
  231.  
  232. // (5)绘制网格
  233. QPen penDotLine;
  234. penDotLine.setStyle(Qt::DotLine);
  235. m_painter->setPen(penDotLine);
  236. for (int i = ; i < POINTSNUM; ++i)
  237. {
  238. // 垂直线
  239. m_painter->drawLine(pointx + (i+)* width/POINTSNUM, pointy,
  240. pointx + (i+)* width/POINTSNUM, pointy - height);
  241. // 水平线
  242. m_painter->drawLine(pointx, pointy-(i+)*height/POINTSNUM,
  243. pointx + width, pointy-(i+)*height/POINTSNUM);
  244. }
  245. }
  246.  
  247. MainWindow::~MainWindow()
  248. {
  249. delete ui;
  250. delete m_painter;
  251. }
  252.  
  253. void MainWindow::paintEvent(QPaintEvent *)
  254. {
  255. QPainter painter(this);
  256. painter.drawImage(, , m_image);
  257. }

(5)main文件

  1. #include "mainwindow.h"
  2. #include <QApplication>
  3.  
  4. int main(int argc, char *argv[])
  5. {
  6. QApplication a(argc, argv);
  7. MainWindow w;
  8. w.show();
  9.  
  10. return a.exec();
  11. }

【2】效果图

运行结果图如下:

Good Good Study, Day Day Up.

顺序 选择 循环 总结

利用QPainter绘制散点图的更多相关文章

  1. PyQt5利用QPainter绘制各种图形

    这个例子我做了好几天: 1)官网C++的源码,改写成PyQt5版本的代码,好多细节不会转化 2)网上的PyQt的例子根本运行不了 填了无数个坑,结合二者,终于能完成了一个关于绘图的东西.这个过程也掌握 ...

  2. 利用QPainter绘制各种图形(Shape, Pen 宽带,颜色,风格,Cap,Join,刷子)

    利用QPainter绘制各种图形 Qt的二维图形引擎是基于QPainter类的.QPainter既可以绘制几何形状(点.线.矩形.椭圆.弧形.弦形.饼状图.多边形和贝塞尔曲线),也可以绘制像素映射.图 ...

  3. 【带着canvas去流浪(4)】绘制散点图

    目录 一. 任务说明 二. 重点提示 三. 示例代码 四.散点hover交互效果的实现 4.1 基本算法 4.2 参考代码 4.3 Demo中的小问题 示例代码托管在:http://www.githu ...

  4. 带着canvas去流浪系列之四 绘制散点图

    [摘要] 用原生canvasAPI实现百度Echarts图表 示例代码托管在:http://www.github.com/dashnowords/blogs 一. 任务说明 使用原生canvasAPI ...

  5. C#利用GDI+绘制旋转文字等效果

    C#中利用GDI+绘制旋转文本的文字,网上有很多资料,基本都使用矩阵旋转的方式实现.但基本都只提及按点旋转,若要实现在矩形范围内旋转文本,资料较少.经过琢磨,可以将矩形内旋转转化为按点旋转,不过需要经 ...

  6. 利用PowerDesigner绘制PDM生成SQL Server数据库

    PowerDesigner是个很强大的建模工具,可以利用它绘制各种图形,本文利用该工具绘制PDM,进而生成SQL Server数据库. 比如绘制一个简单的学生选课.教师授课管理系统的PDM: pk表示 ...

  7. 在OpenCV中利用鼠标绘制矩形和截取图像的矩形区域

    这是两个相关的程序,前者是后者的基础.实际上前一个程序也是在前面博文的基础上做的修改,请参考<在OpenCV中利用鼠标绘制直线> .下面贴出代码. 程序之一,在OpenCV中利用鼠标绘制矩 ...

  8. 利用JFreeChart绘制股票K线图完整解决方案

    http://blog.sina.com.cn/s/blog_4ad042e50100q7d9.html 利用JFreeChart绘制股票K线图完整解决方案 (2011-04-30 13:27:17) ...

  9. Python使用Plotly绘图工具,绘制散点图、线形图

    今天在研究Plotly绘制散点图的方法 使用Python3.6 + Plotly Plotly版本2.0.0 在开始之前先说说,还需要安装库Numpy,安装方法在我的另一篇博客中有写到:https:/ ...

随机推荐

  1. Javascript 面向对象编程(一):封装 作者:yuan一峰

    学习Javascript,最难的地方是什么? 我觉得,Object(对象)最难.因为Javascript的Object模型很独特,和其他语言都不一样,初学者不容易掌握. 下面就是我的学习笔记,希望对大 ...

  2. shell 变量的数值计算实践 expr

    expr(evaluate(求值)expressions(表达式))命令既可以用于整数运算,也可以用于相关字符串长度.匹配等的运算处理 expr 用做计算 必须有一个空格才会计算 [root@salt ...

  3. Linux 磁盘空间大小统计du命令常见使用方法

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/hongweigg/article/details/37692057 在 Linux下,能够对某个文件 ...

  4. 怎样打开U盘最安全

    为了避免电脑使用U盘时,通过双击,或者右击盘符时,导致把病毒感染至整个电脑,因此使用下面的方法,可使U盘病毒不被激活传播. 在取消了U盘自动运行的情况下(在组策略中一定要关闭自动运行功能,否则只要一插 ...

  5. jsp fmt标签格式化double数字

    <fmt:formatNumber value="${zjdl.ygdl }" pattern="0.00" />

  6. K-means &K-medoids 聚类

    k-平均值算法对孤立点很敏感!因为具有特别大的值的对象可能显著地影响数据的分布. k-中心点(k-Medoids): 不采用簇中对象的平均值作为参照点, 而是选用簇中位置最中心的对象, 即中心点(me ...

  7. linux下automake用法

    linux下automake用法 2017年02月06日 09:21:14 阅读数:3684 标签: makemakefilegnulinux   作为Linux下的程序开发人员,大家一定都遇到过Ma ...

  8. 创建vue项目的时候遇到:PhantomJS not found on PATH

    1.提示找不到PhantomJS需要进行下载,如果网速允许的话可以直接 npm install -g phantomjs 如果网速不给力的话,那就先进行淘宝镜像安装 npm install -g cn ...

  9. Linux个人知识扩展:服务器几u的意思,网络带宽

    服务器几u的意思: 指的服务器大小规格 1U=4.45cm 2U=8.9cm 3U=4.45cm * 3 4U=4.45cm * 4 这指的是服务器的高度 现在的服务器为节省空间都是很扁的 U是服务器 ...

  10. jenkins 多选参数构建配置

    参考:https://blog.csdn.net/e295166319/article/details/54017231 场景: 有的时候,参数基本都是那几个,但是不变,但是参数名字比较长,不好记忆, ...