当前位置: 首页 > news >正文

(15)Qt绘图(two)

目录

坐标变换

平移坐标轴

缩放坐标轴

旋转坐标轴

定时器加坐标轴旋转实现动画旋转

transform旋转(可设置旋转轴)

绕X轴旋转

绕Y轴旋转

绕Z轴旋转

错切

Y轴错切

X轴错切

画家的保存与坐标复原

基本图形绘制

绘制点

绘制线

绘制矩形

普通矩形绘制

圆角矩形绘制

 填充矩形绘制

绘制圆形

绘制弧、扇形、弦

绘制弧

绘制扇形

绘制弦

绘制折线

绘制多边形

绘制路径

基本路径绘制

 填充规则

绘制贝塞尔曲线

二次贝塞尔曲线绘制

三次贝塞尔曲线绘制

绘制文字

静态文本绘制

普通文本绘制

字体相关函数

图片绘制

QPixmap

 指定位置裁剪

透明绘制

瓦片图绘制

图像的保存

QImage

QPicture

QBitmap

碰撞检测


坐标变换

平移坐标轴

painter.translate(50,50);
painter.drawPixmap(0,0, QPixmap(":/bk1.jpg").scaled(150,100));

缩放坐标轴

painter.drawPixmap(0,0, QPixmap(":/bk1.jpg").scaled(100,100));
painter.scale(0.5,0.5);
painter.drawPixmap(200,200, QPixmap(":/bk1.jpg").scaled(100,100));

旋转坐标轴

painter.translate(width()/2 - 100,height()/2 - 100);
painter.rotate(30); // 角度(默认以坐标原点旋转)(正数顺时针,负数逆时针)
painter.drawPixmap(0,0, QPixmap(":/bk1.jpg").scaled(200,200));

定时器加坐标轴旋转实现动画旋转

QTimer* timer = new QTimer(this);
timer->callOnTimeout(this, QOverload<>::of(&QWidget::update));
timer->start(10);static int angle = 0;
painter.translate(width()/2 - 100,height()/2 - 100);
painter.rotate(angle++);
painter.drawPixmap(0,0, QPixmap(":/bk1.jpg").scaled(200,200));

transform旋转(可设置旋转轴)

绕X轴旋转

QTimer* timer = new QTimer(this);
timer->callOnTimeout(this, QOverload<>::of(&QWidget::update));
timer->start(10);
//
static int angle = 0;
QTransform transform;
transform.rotate(angle++, Qt::XAxis);   // 绕X轴旋转
painter.setTransform(transform);painter.drawPixmap(0, 0 , QPixmap(":/bk1.jpg").scaled(200,200));

绕Y轴旋转

QTimer* timer = new QTimer(this);
timer->callOnTimeout(this, QOverload<>::of(&QWidget::update));
timer->start(10);
//
static int angle = 0;
QTransform transform;
transform.rotate(angle++, Qt::YAxis);   // 绕Y轴旋转
painter.setTransform(transform);painter.drawPixmap(0, 0 , QPixmap(":/bk1.jpg").scaled(200,200));

绕Z轴旋转

QTimer* timer = new QTimer(this);
timer->callOnTimeout(this, QOverload<>::of(&QWidget::update));
timer->start(10);
//
static int angle = 0;
QTransform transform;
transform.rotate(angle++, Qt::ZAxis);   // 绕Z轴旋转
painter.setTransform(transform);painter.drawPixmap(0, 0 , QPixmap(":/bk1.jpg").scaled(200,200));

错切

Y轴错切

// y轴错切
painter.translate(width()/2 - 100, height()/2 -100);
painter.shear(0, 0.5); // [-1, 1]
painter.drawPixmap(0, 0 , QPixmap(":/bk1.jpg").scaled(200,200));

 

X轴错切

// x轴错切
painter.translate(width()/2 - 100, height()/2 -100);
painter.shear(0.5, 0); // [-1, 1]
painter.drawPixmap(0, 0 , QPixmap(":/bk1.jpg").scaled(200,200));

画家的保存与坐标复原

painter.save();       // 画家状态保存
// 坐标变换
// 图形绘制
painter.restore();    // 画家状态复原

基本图形绘制

绘制点

painter.setPen(Qt::red);
painter.drawPoint(50,50);  // 绘制单个点
// 绘制多个点
QPoint points[] = {{0,0},{1,1},{2,2},{3,3}};
painter->drawPoints(points, 4);
// 绘制多个点
QPolygon polygon;
for(int i = 0; i < 100; i++)
{polygon.append({i,i});
}
painter.drawPoints(polygon);

绘制线

// 绘制一条线
painter.drawLine(0,0,100,100);
// 绘制多条线
QList<QLine> lines = {{0,0,100,100}, {100,100, 0,200}};
painter.drawLines(lines);

绘制矩形

普通矩形绘制

painter.drawRect(50,50,100,100);

圆角矩形绘制

// 最后一个参数为默认值,此时第三第四个参数为具体的值
painter.drawRoundedRect(QRect(200,200,100,100), 50, 50,Qt::SizeMode::AbsoluteSize);

// 此时第三第四个参数为百分比 [0,100]
painter.drawRoundedRect(QRect(200,200,100,100), 50, 50,Qt::SizeMode::RelativeSize);

 填充矩形绘制

painter.fillRect(50,50,100,100,QColor(255,0,255));

绘制圆形

painter.drawEllipse(0,0,200,200);						// 矩形区域绘制
painter.drawEllipse(QPoint(100,100),50,50);				// 中心点,两轴

绘制弧、扇形、弦

绘制弧

painter.drawRect(100,100,200,200);
painter.setPen(Qt::red);
painter.drawArc(QRect(100,100,200,200), 0, 16 * 90);

绘制扇形

painter.drawRect(100,100,200,200);
painter.setPen(Qt::red);
painter.drawPie(QRect(100,100,200,200), 0, 16 * 90);

绘制弦

painter.drawRect(100,100,200,200);
painter.setPen(Qt::red);
painter.drawChord(QRect(100,100,200,200), 0, 16 * 90);

绘制折线

QPolygon poly;
poly << QPoint(0, 0) << QPoint(100,100) << QPoint(200, 100);
painter.drawPolyline(poly);
QPoint pos[3] = { QPoint(0, 0) , QPoint(100,100) , QPoint(200, 100)};
painter.drawPolyline(pos, 3);

 

绘制多边形

painter.setBrush(Qt::green);
QPolygon poly = {{0,0},{100,0},{100,100},{0,100},{200,0}};
painter.drawPolygon(poly);

绘制路径

基本路径绘制

painter.setBrush(Qt::green);
QPainterPath path;
path.lineTo(200,200);
path.lineTo(0,200);
path.moveTo(400,400);
path.lineTo(width(),height());
painter.drawPath(path);

 填充规则

painter.setBrush(Qt::green);
QPainterPath path;
path.addRect(QRect(0,0,200,200));
path.addRect(QRect(100,100,200,200));
path.setFillRule(Qt::FillRule::WindingFill);      // 缠绕填充
//path.setFillRule(Qt::FillRule::OddEvenFill);    // 奇偶填充
painter.drawPath(path);

绘制贝塞尔曲线

二次贝塞尔曲线绘制

// 二次贝塞尔曲线
QPainterPath path;
path.moveTo(200,200);
path.quadTo(QPoint(300,300), QPoint(400,200));
painter.drawPath(path);

三次贝塞尔曲线绘制

// 三次贝塞尔曲线
QPainterPath path;
path.moveTo(0,0);
path.cubicTo(QPoint(10,100), QPoint(300,500), QPoint(200,200));
painter.drawPath(path);

绘制文字

静态文本绘制

// 绘制坐标即为左上角坐标
painter.drawStaticText(QPoint(0,0), QStaticText("Hello World"));

普通文本绘制

注意: 绘制文字是以左下角为原点绘制的

painter.setPen(Qt::red);
painter.setFont(QFont("微软雅黑",28,QFont::Bold,true));
painter.drawText(0,50, QString("Hello World"));

 

// 将绘制字体固定在矩形区域内 (会自动换行)
painter.drawText(QRect(0,0,100,200), "Hello World Hello World!");

 

字体相关函数

// 设置字体
painter->setFont();
// 获取字体
painter->font();
// 获取字体信息
painter->fontInfo();
// 获取字体数据
painter->fontMetrics();

图片绘制

QPixmap

针对输出显示优化的图像绘制

 

 指定位置裁剪

painter.drawPixmap(100, 100, QPixmap("mm.jpg").scaled(100,100));
painter.drawPixmap(QRect(0,0,100,100),                  // 绘制位置QPixmap("mm.jpg").scaled(100,100),   // 图像QRect(50,50,50,50));                 // 裁剪区域

drawPixmap(const QPoint &point, const QPixmap &pixmap, const QRect &source)

透明绘制

分别准备一张原码图和一张掩码图

 

//掩码图和原图大小必须一致
//掩码图白色区域为透明,黑色区域为绘制
painter.setRenderHint(QPainter::RenderHint::Antialiasing);
QBitmap mask("mask.jpg");
QPixmap pix = QPixmap("snowball.jpg").scaled(mask.size());
pix.setMask(mask);
painter.drawPixmap(0, 0,pix);

瓦片图绘制

// 函数原型
drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, QPainter::PixmapFragmentHints hints = PixmapFragmentHints())
QPainter::PixmapFragment pixFrag = QPainter::PixmapFragment::create(QPointF(0,0), QRectF(0,0,100,100));
painter.drawPixmapFragments(&pixFrag, 2, QPixmap("mm.jpg").scaled(100,100));

图像的保存

m_pixmap = QPixmap(640,480);
QPainter painter(&m_pixmap);
painter.fillRect(m_pixmap.rect(),Qt::blue);
// 保存图片
m_pixmap.save("hello.png");

QImage

专门进行图像处理的

QImage m_img = QImage(640,480,QImage::Format_RGBA8888);
m_img.fill(Qt::transparent);
QPainter painter(&m_img);
painter.fillRect(QRect(0,0,100,100), Qt::blue);
m_img.save("img.png");

QPicture

Qt独有的图像格式

QPainter painter;
painter.begin(&pic);
painter.drawEillipse(0,0,200,200);
painter.end();
pic.save("pic.pic");// 绘制不能直接使用QPicture的构造函数加载文件
QPicture pict;
pict.load("pic.pic");
painter->drawPicture(0,0,pict);

QBitmap

位图(黑白图)

QBitmap bitmap("mm.jpg");
painter.drawImage(QRect(0, 0, 100, 100), bitmap.toImage());

碰撞检测

// 碰撞检测
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QStaticText>
#include <QPainterPath>
#include <QKeyEvent>// 碰撞检测
class Sprite
{
public:Sprite() = default;Sprite(int x,int y,int w,int h, const QPixmap& pix):m_pos(x,y),m_size(w,h),m_pixmap(pix){}void draw(QPainter* painter){painter->drawPixmap(QRect(m_pos,m_size), m_pixmap);}void setPos(int x,int y){m_pos.rx() = x;m_pos.ry() = y;}void moveBy(int dx,int dy){m_pos.rx() += dx;m_pos.ry() += dy;}void updateCollider(){collider.clear();collider.addRect(QRect(m_pos, m_size));}void printPos(){qInfo() << m_pos;}
private:QPoint m_pos;QSize  m_size;QPixmap m_pixmap;
public:QPainterPath collider;  // 碰撞器
};class Widget : public QWidget
{Q_OBJECT
public:Widget(QWidget* parent = nullptr):QWidget(parent){resize(640,480);sp1 = new Sprite(0,0,50,50,QPixmap("mm.jpg"));sp2 = new Sprite(100,0,50,50, QPixmap("snowball.jpg"));}~Widget(){}
protected:void paintEvent(QPaintEvent* ev) override{QPainter painter(this);sp1->draw(&painter);sp2->draw(&painter);}void keyPressEvent(QKeyEvent *ev) override{switch(ev->key()){case Qt::Key_Up:sp2->moveBy(0, -3);break;case Qt::Key_Down:sp2->moveBy(0, 3);break;case Qt::Key_Left:sp2->moveBy(-3, 0);break;case Qt::Key_Right:sp2->moveBy(3, 0);break;}if(sp1->collider.intersects(sp2->collider)){sp2->setPos(width() - 50, 0);}update();// 判断碰撞sp2->updateCollider();sp1->updateCollider();}
private:Sprite* sp1 = nullptr;Sprite* sp2 = nullptr;
};int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}
#include "main.moc"

相关文章:

(15)Qt绘图(two)

目录 坐标变换 平移坐标轴 缩放坐标轴 旋转坐标轴 定时器加坐标轴旋转实现动画旋转 transform旋转&#xff08;可设置旋转轴&#xff09; 绕X轴旋转 绕Y轴旋转 绕Z轴旋转 错切 Y轴错切 X轴错切 画家的保存与坐标复原 基本图形绘制 绘制点 绘制线 绘制矩形 普…...

用队列实现栈——数据结构与算法

&#x1f636;‍&#x1f32b;️Take your time ! &#x1f636;‍&#x1f32b;️ &#x1f4a5;个人主页&#xff1a;&#x1f525;&#x1f525;&#x1f525;大魔王&#x1f525;&#x1f525;&#x1f525; &#x1f4a5;代码仓库&#xff1a;&#x1f525;&#x1f525;魔…...

Python“牵手”1688商品详情页数据采集方法,1688API接口申请指南

1688详情接口 API 是开放平台提供的一种 API 接口&#xff0c;它可以帮助开发者获取商品的详细信息&#xff0c;包括商品的标题、描述、图片等信息。在电商平台的开发中&#xff0c;详情接口API是非常常用的 API&#xff0c;因此本文将详细介绍详情接口 API 的使用。 一、1688…...

记录第一篇被”华为开发者联盟鸿蒙专区 “收录的文章

记录第一篇被”华为开发者联盟鸿蒙专区 “社区收录的文章。 坚持写作的动力是什么&#xff1f; 是记录、分享&#xff0c;以及更好的思考 。...

jenkins的cicd操作

cicd概念 持续集成&#xff08; Continuous Integration&#xff09; 持续频繁的&#xff08;每天多次&#xff09;将本地代码“集成”到主干分支&#xff0c;并保证主干分支可用 持续交付&#xff08;Continuous Delivery&#xff09; 是持续集成的下一步&#xff0c;持续…...

【C++】异常exception

文章目录 1. C语言中传统的处理错误方法2. C中的异常3. 异常的使用3.1 异常的抛出和捕获3.2 异常的重新抛出3.3 异常安全3.4 异常规范 4. 自定义异常体系5. 异常的优缺点 &#x1f4dd; 个人主页 &#xff1a;超人不会飞)&#x1f4d1; 本文收录专栏&#xff1a;《C的修行之路》…...

2023-08-06力扣今日三题

链接&#xff1a; 剑指 Offer 59 - I. 滑动窗口的最大值 题意&#xff1a; 一个lg长度的数组&#xff0c;一个长度k的滑动窗口&#xff0c;求所有滑动窗口中的最大值 解&#xff1a; 优先队列存储存储下标&#xff0c;数字大的优先&#xff0c;每次判断最大的值是否在范围…...

kubeasz在线安装K8S集群

一、介绍 Kubeasz 是一个基于 Ansible 自动化工具&#xff0c;用于快速部署和管理 Kubernetes 集群的工具。它支持快速部署高可用的 Kubernetes 集群&#xff0c;支持容器化部署&#xff0c;可以方便地扩展集群规模&#xff0c;支持多租户&#xff0c;提供了强大的监控和日志分…...

Vue中实现Web端鼠标横向滑动和触控板滑动效果

系列文章目录 文章目录 系列文章目录前言一、鼠标横向滑动效果二、触控板滑动效果总结 前言 在Web端&#xff0c;我们经常需要实现鼠标横向滑动和触控板滑动的效果&#xff0c;以便在页面中展示横向滑动的内容。本文将介绍如何使用Vue和JavaScript来实现这两种效果&#xff0c…...

hdu5-Touhou Red Red Blue(贪心)

Problem - 7329 (hdu.edu.cn) 参考&#xff1a;题解 | #1006.Touhou Red Red Blue# 2023杭电暑期多校5 题解&#xff1a;&#xff08;贪心&#xff09; mp[R], mp[G], mp[P] 分别记录对应字母出现过多少次&#xff0c;没有AAA orABC 出现时不得分也不进行任何操作&#xff…...

【LeetCode 75】第二十三题(2352)相等行列对

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码运行结果&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目很简洁&#xff0c;就是要我们寻找行与列相同的对数。相同行与列不仅是要元素相同&#xff0c;还需要顺序也一样&#xff08…...

【云原生】详细学习Docker-Swarm部署搭建和基本使用

个人主页&#xff1a;征服bug-CSDN博客 kubernetes专栏&#xff1a;云原生_征服bug的博客-CSDN博客 目录 Docker-Swarm编排 1.概述 2.docker swarm优点 3.节点类型 4.服务和任务 5.路由网格 6.实践Docker swarm 1.概述 Docker Swarm 是 Docker 的集群管理工具。它将 Doc…...

awk相关知识点整理

1.awk的使用方法 1.1 语法 awk [options] script varvalue file(s) awk [options] -f scriptfile varvalue file1.2 命令常用选项 -F fs&#xff1a;fs指定输入分隔符&#xff0c;fs可以是字符串或正则表达式&#xff0c;如-F: -v varvalue&#xff1a;赋值一个用户定义变量…...

Mybatis案例-商品的增删改查

文章目录 1. aim2.环境准备3.查询3.1 查所有3.2 查看详情3.3 条件查询3.3.1 Mybatics如何接收参数&#xff1f;3.3.2 多条件查询3.3.3 动态条件查询3.3.4 单条件查询 4.添加主键返回 5.修改5.1 修改全部字段5.2 修改动态字段 6.删除6.1 删除1个6.2 批量删除 JDBC完成&#xff1…...

图像识别模型与训练策略

图像预处理 1.需要将图像Resize到相同大小输入到卷积网络中 2.翻转、裁剪、色彩偏移等操作 3.转化为Tensor数据格式 4.对RGB三种颜色通道进行标准化 data_transforms {train: transforms.Compose([transforms.Resize([96, 96]),transforms.RandomRotation(45),#随机旋转&…...

算法工程师-机器学习面试题总结(3)

FM模型 FM模型与逻辑回归相比有什么优缺点&#xff1f; FM&#xff08;因子分解机&#xff09;模型和逻辑回归是两种常见的预测建模方法&#xff0c;它们在一些方面有不同的优缺点。 FM模型的优点&#xff1a; 1. 能够捕获特征之间的交互作用&#xff1a;FM模型通过对特征向量…...

ROS2学习(五)进程内topic高效通信

对ROS2有一定了解后&#xff0c;我们会发现ROS2中节点和ROS1中节点的概率有很大的区别。在ROS1中节点是最小的进程单元。在ROS2中节点与进程和线程的概念完全区分开了。具体区别可以参考 ROS2学习(四)进程&#xff0c;线程与节点的关系。 在ROS2中同一个进程中可能存在多个节点…...

算法-最大数

给定一组非负整数 nums&#xff0c;重新排列每个数的顺序&#xff08;每个数不可拆分&#xff09;使之组成一个最大的整数。 注意&#xff1a;输出结果可能非常大&#xff0c;所以你需要返回一个字符串而不是整数。 输入&#xff1a;nums [10,2] 输出&#xff1a;"210&…...

Spark中使用RDD算子GroupBy做词频统计的方法

测试文件及环境 测试文件在本地D://tmp/spark.txt&#xff0c;Spark采用Local模式运行&#xff0c;Spark版本3.2.0&#xff0c;Scala版本2.12&#xff0c;集成idea开发环境。 hello world java world java java实验代码 import org.apache.spark.rdd.RDD import org.apache.…...

如何使用Kafka构建事件驱动的架构

事件驱动的架构(EDA)是一种软件设计模式&#xff0c;它关注事件的生成、检测和使用&#xff0c;以支持高效和可扩展的系统。在EDA中&#xff0c;事件是组件之间通信的主要手段&#xff0c;允许它们实时交互和响应更改。这种架构促进了松散耦合、可扩展性和响应性&#xff0c;使…...

开发者专属提示词库:提升AI协作效率的实战指南

1. 项目概述&#xff1a;一个为开发者量身定制的提示词宝库如果你是一名开发者&#xff0c;无论是前端、后端、运维还是算法工程师&#xff0c;我相信你都或多或少地接触过像 ChatGPT 这类大型语言模型。它们能写代码、解 Bug、解释概念&#xff0c;甚至帮你设计架构。但很多时…...

终极CoreCycler完全指南:5步掌握CPU单核稳定性测试与精准调校

终极CoreCycler完全指南&#xff1a;5步掌握CPU单核稳定性测试与精准调校 【免费下载链接】corecycler Script to test single core stability, e.g. for PBO & Curve Optimizer on AMD Ryzen or overclocking/undervolting on Intel processors 项目地址: https://gitco…...

安全聚合技术:原理、实现与多场景应用

1. 安全聚合技术概述安全聚合&#xff08;Secure Aggregation&#xff09;是一种多方安全计算技术&#xff0c;它允许多个互不信任的参与方在不泄露各自私有数据的前提下&#xff0c;共同计算出一个聚合结果。这项技术的核心价值在于解决了数据隐私与数据共享之间的矛盾&#x…...

基于LLM的长文本摘要工具SumGPT:从原理到本地化部署实战

1. 项目概述&#xff1a;一个为长文本摘要而生的智能工具最近在折腾一些文档处理的工作流&#xff0c;发现一个挺普遍但很烦人的痛点&#xff1a;面对动辄几十页的PDF报告、冗长的会议纪要或是海量的研究论文&#xff0c;想要快速抓住核心要点&#xff0c;简直像大海捞针。手动…...

深入解析go-containerregistry:无守护进程的容器镜像操作利器

1. 项目概述&#xff1a;容器镜像的“瑞士军刀”如果你在容器化这条路上已经走了一段时间&#xff0c;那么对“镜像”这个概念一定不会陌生。无论是 Docker Hub 上的nginx:latest&#xff0c;还是你公司私有仓库里的myapp:v1.2.3&#xff0c;这些镜像都是容器世界的基石。但你是…...

TransPrompt:结构化提示词工程,提升LLM应用开发效率

1. 项目概述&#xff1a;当提示词工程遇上结构化工具最近在折腾大语言模型应用开发的朋友&#xff0c;估计都绕不开一个核心痛点&#xff1a;如何高效、稳定地管理那些越来越复杂、越来越长的提示词&#xff08;Prompt&#xff09;。直接写在代码里&#xff1f;改起来麻烦&…...

大语言模型分步推理与自我验证框架:提升AI生成准确性的工程实践

1. 项目概述&#xff1a;当AI学会“自我验证”最近在开源社区里&#xff0c;一个名为“Lets-Verify-Step-by-Step”的项目引起了我的注意。这个项目直指当前大语言模型&#xff08;LLM&#xff09;应用中的一个核心痛点&#xff1a;如何让模型在生成复杂答案时&#xff0c;能像…...

【Clickhouse从入门到精通】第08篇:揭秘ClickHouse为何如此之快——五大设计哲学

上一篇【第07篇】ClickHouse执行引擎架构——Parser、Interpreter与Function体系 下一篇【第09篇】ClickHouse安装部署全攻略——从环境准备到服务启动 摘要 ClickHouse能在十亿行级别数据的聚合查询中实现毫秒级响应&#xff0c;绝非偶然。这种极致性能的背后&#xff0c;是一…...

基于MCP协议构建Reddit社区趋势分析工具:架构、部署与应用

1. 项目概述&#xff1a;一个实时洞察社区脉搏的利器最近在做一个社区运营相关的项目&#xff0c;需要实时追踪几个特定话题在Reddit上的讨论热度变化。手动刷帖、统计关键词频率这种笨办法效率太低&#xff0c;而且很难量化趋势。就在我琢磨着是不是要自己写个爬虫加分析脚本的…...

React Native聊天UI组件库集成指南:从Sendbird UIKit入门到高级定制

1. 项目概述&#xff1a;一个开箱即用的React Native聊天UI组件库如果你正在用React Native开发一个需要集成聊天功能的App&#xff0c;并且希望这个聊天界面看起来专业、交互流畅&#xff0c;同时你又不想从零开始造轮子&#xff0c;那么你很可能已经听说过或者正在寻找一个合…...