利用QPainter绘制散点图
【1】实例代码
(1)代码目录结构(备注:QtCreator默认步骤新建工程)
(2)工程pro文件
QT += core gui greaterThan(QT_MAJOR_VERSION, ): QT += widgets TARGET = painter
TEMPLATE = app SOURCES += main.cpp\
mainwindow.cpp HEADERS += mainwindow.h FORMS += mainwindow.ui
(3)头文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H #include <QtGui>
#include <QPaintEvent>
#include <QMainWindow> #include <ctime>
#include <cstdlib> namespace Ui
{
class MainWindow;
} class MainWindow : public QMainWindow
{
Q_OBJECT public:
explicit MainWindow(QWidget *parent = );
~MainWindow(); void Paint(); public slots:
void onRefresh();
protected:
void paintEvent(QPaintEvent *); private:
Ui::MainWindow *ui;
QImage m_image;
QPainter *m_painter;
}; #endif // MAINWINDOW_H
(4)实现文件
#include "mainwindow.h"
#include "ui_mainwindow.h" #define POINTSNUM 10
#define LowerFactor 0.8
#define UpperFactor 1.2 typedef struct Data
{
double scaleRange;
double maxScale;
double minScale;
QVector<double> vecData; Data() : scaleRange(0.0), maxScale(0.0), minScale(0.0)
{}
void init()
{
for (int i = ; i < POINTSNUM; ++i)
{
if (i % )
vecData.append(rand() % - );
else
vecData.append(rand() % + );
}
double maxElement = *(std::max_element(vecData.begin(), vecData.end()));
double minElement = *(std::min_element(vecData.begin(), vecData.end()));
if (maxElement < )
{
maxScale = maxElement * LowerFactor;
minScale = minElement * UpperFactor;
}
else if ( == maxElement)
{
maxScale = ;
minScale = minElement * UpperFactor;
}
else if (maxElement > && minElement < )
{
maxScale = maxElement * UpperFactor;
minScale = minElement * UpperFactor;
}
else if (minElement > )
{
maxScale = maxElement * UpperFactor;
minScale = minElement * LowerFactor;
} scaleRange = maxScale - minScale;
}
void print()
{
for (int i = ; i < POINTSNUM; ++i)
{
qDebug () << i << "::" << vecData[i] << " ";
}
qDebug() << endl;
}
}DataInfo; MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->mainToolBar->setVisible(true); QAction *pAction = new QAction("refresh", this);
ui->mainToolBar->addAction(pAction);
connect(pAction, &QAction::triggered, this, &MainWindow::onRefresh); resize(, ); // 窗体大小 宽度1000 高度730 m_image = QImage(, , QImage::Format_RGB32); // 画布的初始化大小设为,使用32位颜色
QColor backColor = qRgb(, , ); // 画布初始化背景色使用白色
m_image.fill(backColor); // 对画布进行填充 m_painter = new QPainter(&m_image);
m_painter->setRenderHint(QPainter::Antialiasing, true); // 设置反锯齿模式 Paint();
} void MainWindow::onRefresh()
{
m_painter->fillRect(, , - , - , Qt::white);
Paint();
update();
} void MainWindow::Paint()
{
// 确定坐标轴起点坐标
int pointx = , pointy = ; // 确定坐标轴宽度和高度,上文已定义画布大小,宽高依此而定。
int width = - pointx - ; // 宽度 = 画布宽度 - 坐标起点x - 右端间隙
int height = - * ; // 高度 = 画布高度 - 上下端的间隙高度 // 绘制视图区域
// 即外围的矩形(由左上角与右下角的两个点确定一个矩形)
m_painter->drawRect(, , - , - ); // 绘制X、Y1、Y2轴
QPointF xStartPoint(pointx, pointy);
QPointF xEndPoint(width + pointx, pointy);
m_painter->drawLine(xStartPoint, xEndPoint); // 坐标轴x宽度为width QPointF y1StartPoint(pointx, pointy - height);
QPointF y1EndPoint(pointx, pointy);
m_painter->drawLine(y1StartPoint, y1EndPoint); // 坐标轴y1高度为height QPointF y2StartPoint(pointx + width, pointy - height);
QPointF y2EndPoint(pointx + width, pointy);
m_painter->drawLine(y2StartPoint, y2EndPoint); // 坐标轴y2高度为height // (2)获得数据并分析最大值与最小值
DataInfo vectorX, vectorY1, vectorY2; // 数据储存在容器中,大小为POINTSNUM]
// 模拟随机数据
srand((int)time(NULL));
vectorX.init();
vectorY1.init();
vectorY2.init(); vectorX.print();
vectorY1.print();
vectorY2.print(); double kx = (double)(width / vectorX.scaleRange); // x轴的系数
double ky1 = (double)(height / vectorY1.scaleRange); // y1方向的比例系数
double ky2 = (double)(height / vectorY2.scaleRange); // y2方向的比例系数 // (3)绘制点
QPen penPointY1, penPointY2;
penPointY1.setColor(Qt::blue);
penPointY1.setWidth(); penPointY2.setColor(Qt::red);
penPointY2.setWidth(); for (int i = ; i < POINTSNUM; ++i)
{
double dXStart = pointx + kx * (vectorX.vecData[i] - vectorX.minScale);
m_painter->setPen(penPointY1); // 蓝色的笔,用于标记Y1各个点
m_painter->drawPoint(dXStart, pointy - (vectorY1.vecData[i] - vectorY1.minScale) * ky1); m_painter->setPen(penPointY2); // 红色的笔,用于标记Y2各个点
m_painter->drawPoint(dXStart, pointy - (vectorY2.vecData[i] - vectorY2.minScale) * ky2);
} // (4) 绘制刻度线
QPen penDegree;
penDegree.setColor(Qt::black);
penDegree.setWidth();
m_painter->setPen(penDegree); // x轴刻度线和值
// x轴 第一个刻度值
m_painter->drawText(pointx + , pointy + , QString::number(vectorX.minScale, 'f', ));
for (int i = ; i < POINTSNUM - ; ++i) // 分成10份
{
// // 选取合适的坐标,绘制一段长度为4的直线,用于表示刻度
// m_painter->drawLine(pointx + (i + 1) * width/10, pointy,
// pointx + (i+1)*width/10, pointy + 4); m_painter->drawText(pointx + (i+0.9) * width / POINTSNUM, pointy + , // 值的位置信息
QString::number(vectorX.minScale + (i+) * (vectorX.scaleRange/POINTSNUM), 'f', ));
}
// x轴 最后一个刻度值
m_painter->drawText(pointx + (POINTSNUM - + 0.8) * width / POINTSNUM, pointy + ,
QString::number(vectorX.maxScale, 'f', )); xStartPoint.setX(pointx);
xStartPoint.setY(pointy + );
xEndPoint.setX(pointx + width);
xEndPoint.setY(pointy + );
m_painter->drawLine(xStartPoint, xEndPoint); m_painter->drawText(pointx + width/, pointy + , QString("X")); // y1轴刻度线和值
// y1轴 第一个刻度值
m_painter->drawText(pointx - , pointy - , QString::number(vectorY1.minScale, 'f', ));
for (int i = ; i < POINTSNUM - ; ++i)
{
// 代码较长,但是掌握基本原理即可。
// 主要就是确定一个位置,然后画一条短短的直线表示刻度。 // m_painter->drawLine(pointx, pointy-(i+1)*height/10,
// pointx-4, pointy-(i+1)*height/10); m_painter->drawText(pointx - , pointy - (i+0.85) * height/POINTSNUM,
QString::number(vectorY1.minScale + (i+) * (vectorY1.scaleRange/POINTSNUM), 'f', ));
}
// y1轴 最后一个刻度值
m_painter->drawText(pointx - , pointy - (POINTSNUM - + 0.85) * height/POINTSNUM,
QString::number(vectorY1.maxScale, 'f', )); y1StartPoint.setX(pointx - );
y1StartPoint.setY(pointy - height); y1EndPoint.setX(pointx - );
y1EndPoint.setY(pointy);
m_painter->drawLine(y1StartPoint, y1EndPoint); m_painter->drawText(pointx - , pointy - height/, QString("Y1")); // y2轴刻度线和值
// y2轴 第一个刻度值
m_painter->drawText(pointx + width + , pointy - , QString::number(vectorY2.minScale, 'f', ));
for (int i = ; i < POINTSNUM - ; ++i)
{
// m_painter->drawLine(pointx + width, pointy-(i+1)*height/10,
// pointx + width + 4, pointy-(i+1)*height/10); m_painter->drawText(pointx + width + , pointy - (i+0.85)*height/POINTSNUM,
QString::number((vectorY2.minScale + (i+)*(vectorY2.scaleRange/POINTSNUM)), 'f' , ));
}
// Y2轴 最后一个刻度值
m_painter->drawText(pointx + width + , pointy - (POINTSNUM - + 0.85)*height/POINTSNUM,
QString::number(vectorY2.maxScale, 'f', )); y2StartPoint.setX(pointx + width + );
y2StartPoint.setY(pointy - height); y2EndPoint.setX(pointx + width + );
y2EndPoint.setY(pointy);
m_painter->drawLine(y2StartPoint, y2EndPoint); m_painter->drawText(pointx + width + , pointy - height/, QString("Y2")); // (5)绘制网格
QPen penDotLine;
penDotLine.setStyle(Qt::DotLine);
m_painter->setPen(penDotLine);
for (int i = ; i < POINTSNUM; ++i)
{
// 垂直线
m_painter->drawLine(pointx + (i+)* width/POINTSNUM, pointy,
pointx + (i+)* width/POINTSNUM, pointy - height);
// 水平线
m_painter->drawLine(pointx, pointy-(i+)*height/POINTSNUM,
pointx + width, pointy-(i+)*height/POINTSNUM);
}
} MainWindow::~MainWindow()
{
delete ui;
delete m_painter;
} void MainWindow::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.drawImage(, , m_image);
}
(5)main文件
#include "mainwindow.h"
#include <QApplication> int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show(); return a.exec();
}
【2】效果图
运行结果图如下:
Good Good Study, Day Day Up.
顺序 选择 循环 总结
利用QPainter绘制散点图的更多相关文章
- PyQt5利用QPainter绘制各种图形
这个例子我做了好几天: 1)官网C++的源码,改写成PyQt5版本的代码,好多细节不会转化 2)网上的PyQt的例子根本运行不了 填了无数个坑,结合二者,终于能完成了一个关于绘图的东西.这个过程也掌握 ...
- 利用QPainter绘制各种图形(Shape, Pen 宽带,颜色,风格,Cap,Join,刷子)
利用QPainter绘制各种图形 Qt的二维图形引擎是基于QPainter类的.QPainter既可以绘制几何形状(点.线.矩形.椭圆.弧形.弦形.饼状图.多边形和贝塞尔曲线),也可以绘制像素映射.图 ...
- 【带着canvas去流浪(4)】绘制散点图
目录 一. 任务说明 二. 重点提示 三. 示例代码 四.散点hover交互效果的实现 4.1 基本算法 4.2 参考代码 4.3 Demo中的小问题 示例代码托管在:http://www.githu ...
- 带着canvas去流浪系列之四 绘制散点图
[摘要] 用原生canvasAPI实现百度Echarts图表 示例代码托管在:http://www.github.com/dashnowords/blogs 一. 任务说明 使用原生canvasAPI ...
- C#利用GDI+绘制旋转文字等效果
C#中利用GDI+绘制旋转文本的文字,网上有很多资料,基本都使用矩阵旋转的方式实现.但基本都只提及按点旋转,若要实现在矩形范围内旋转文本,资料较少.经过琢磨,可以将矩形内旋转转化为按点旋转,不过需要经 ...
- 利用PowerDesigner绘制PDM生成SQL Server数据库
PowerDesigner是个很强大的建模工具,可以利用它绘制各种图形,本文利用该工具绘制PDM,进而生成SQL Server数据库. 比如绘制一个简单的学生选课.教师授课管理系统的PDM: pk表示 ...
- 在OpenCV中利用鼠标绘制矩形和截取图像的矩形区域
这是两个相关的程序,前者是后者的基础.实际上前一个程序也是在前面博文的基础上做的修改,请参考<在OpenCV中利用鼠标绘制直线> .下面贴出代码. 程序之一,在OpenCV中利用鼠标绘制矩 ...
- 利用JFreeChart绘制股票K线图完整解决方案
http://blog.sina.com.cn/s/blog_4ad042e50100q7d9.html 利用JFreeChart绘制股票K线图完整解决方案 (2011-04-30 13:27:17) ...
- Python使用Plotly绘图工具,绘制散点图、线形图
今天在研究Plotly绘制散点图的方法 使用Python3.6 + Plotly Plotly版本2.0.0 在开始之前先说说,还需要安装库Numpy,安装方法在我的另一篇博客中有写到:https:/ ...
随机推荐
- 【python基础】迭代器和生成器函数
1.迭代器协议: 1.迭代器协议是指:对象必须提供一个 __next__() 方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代(只能往后走不能往前退) ...
- nmap常用参数
总结: 主机发现 -sn 防止NMAP端口扫描 -SP TCP 半连接扫描,默认是通过80端口来发现主机的 -SA ACK ping 扫描 -SU UDP ping 扫描 不好 ...
- (3.15)mysql基础深入——mysql默认数据库/系统数据库
(3.15)mysql基础深入——mysql默认数据库 关键词:Mysql默认数据库,mysql系统数据库 系统数据库的组成 一共4个 [1]information_schema(可以理解成字典表) ...
- centos安装Django之二:pip3安装
前面我们说到了centos安装Django之一:安装openssl,现在我们进入第二阶段pip3安装.两步实现:安装setuptools(pypi),安装pip,下面就和ytkah一起看看配置吧 1. ...
- C++读取dll文件所在目录
////保证config.txt从本DLL目录位置读取 //获取DLL自身所在路径(此处包括DLL文件名) }; GetModuleFileNameA((HINSTANCE)&__ImageB ...
- [py][mx]django处理登录逻辑
浏览器同源策略(same-origin policy) csrf攻击防御核心点总结 django的cookie和session操作-7天免登录 flask操作cookie&django的see ...
- python-lambda、filter、reduce、map
python-lambda.map.filter.reduce lamdba python关键字,用于在表达式中创建匿名函数. 注意:lambda函数的定义体只能用纯表达式,不能赋值,不能使用whil ...
- vue项目中别个访问你的本地调试需要改东西
- SwingBench 字符模式压测最佳实践
之前写过<使用SwingBench 对Oracle RAC DB性能 压力测试>,使用的是最基础直观的图形模式,已经可以满足大多数需求. 但是在有些场景下,图形模式可能本身消耗资源过大,尤 ...
- model.addattribute()的作用
1.往前台传数据,可以传对象,可以传List,通过el表达式 ${}可以获取到, 类似于request.setAttribute("sts",sts)效果一样. 2.@ModelA ...