【Qt开发流程】之2D绘图1:概述及基本绘制与填充和渐变填充

news2024/11/23 11:15:02

概述

Qt的绘图系统可以使用相同的API在屏幕和打印设备上进行绘图,并且主要基于QPainter, QPaintDeviceQPaintEngine类。
QPainter用于执行绘图操作,QPaintDevice是一个二维空间的抽象,可以使用QPainter在其上绘制,QPaintEngine提供了QPainter用于在不同类型的设备上绘制的接口。QPaintEngine类在QPainterQPaintDevice内部使用,并且对应用程序程序员是隐藏的,除非他们创建自己的设备类型。

这种方法的主要好处是,所有的绘制都遵循相同的绘制方式,从而很容易添加对新特性的支持,并为不支持的特性提供默认实现。

以下类为QPainter绘制提供了支持:

描述
QBitmap单色(1位深度)像素图
QBrush定义由QPainter绘制的形状的填充模式
QColor基于RGB, HSV或CMYK值的颜色
QColormap将与设备无关的QColors映射到与设备相关的像素值
QConicalGradient与QBrush结合使用,指定锥形梯度刷
QFont指定用于绘制文本的字体
QFontMetrics字体度量信息
QFontMetricsF字体度量信息
QGenericMatrix模板类,表示有N列和M行的NxM变换矩阵
QGradient与QBrush结合使用来指定渐变填充
QIcon不同模式和状态下的可伸缩图标
QIconEngineQIcon渲染器的抽象基类
QImage独立于硬件的图像表示,允许直接访问像素数据,并且可以用作绘画设备
QImageReader格式独立的接口,读取图像从文件或其他设备
QImageWriter用于将图像写入文件或其他设备的格式独立接口
QLine二维矢量采用整数精度
QLineF二维矢量使用浮点精度
QLinearGradient与QBrush结合使用,指定线性梯度刷
QMargins定义矩形的四个边距
QMarginsF定义矩形的四个边距
QPagedPaintDevice表示支持多个页面的绘图设备
QPaintDevice可以用QPainter绘制的对象的基类
QPaintEngineQPainter如何在给定平台上绘制给定设备的抽象定义
QPainter在小部件和其他绘制设备上执行低级绘制
QPainterPath用于绘制操作的容器,使图形形状能够被构造和重用
QPainterPathStroker用于为给定的画家路径生成可填充的轮廓
QPdfWriter类生成可用作绘图设备的pdf
QPen定义QPainter应该如何绘制形状的线条和轮廓
QPixmap可以用作绘画设备的屏幕外图像表示
QPlatformFontDatabase可以自定义字体的发现方式和呈现方式
QPoint使用整数精度在平面上定义一个点
QPointF使用浮点精度在平面上定义一个点
QPolygon向量点使用整数精度
QPolygonF向量点使用浮点精度
QRadialGradient与QBrush结合使用,指定径向梯度刷
QRect使用整数精度在平面上定义一个矩形
QRectF使用浮点精度在平面中定义一个矩形
QRegion指定绘图器的剪辑区域
QSize使用整数点精度定义二维对象的大小
QSizeF使用浮点精度定义二维对象的大小
QStylePainter用于在小部件内绘制QStyle元素的方便类
QSupportedWritingSystems在使用内部Qt字体数据库注册字体时使用
QSvgGenerator用于创建SVG绘图的绘图设备
QSvgRenderer用于将SVG文件的内容绘制到绘图设备上
QSvgWidget小部件,用于显示可缩放矢量图形(SVG)文件的内容
QTransform指定坐标系统的2D转换
QVector2D表示二维空间中的向量或顶点

创建绘画设备

QPaintDevice类是可以绘制对象的基类,也就是说,QPainter可以在任何QPaintDevice子类上绘制。QPaintDevice的绘图功能是由QWidgetQImageQPixmapQPictureQPrinterQOpenGLPaintDevice实现的。

Widget

QWidget类是Qt Widgets模块中用户界面元素的基类。它接收来自窗口系统的鼠标、键盘和其他事件,并在屏幕上描绘自己的表示。

Image

QImage类提供了一个独立于硬件的图像表示,它是为I/O和直接的像素访问和操作而设计和优化的。QImage支持多种图像格式,包括单色,8位,32位和alpha混合图像。
使用QImage作为绘图设备的一个优点是,它可以以与平台无关的方式保证任何绘图操作的像素准确性。另一个好处是,绘制可以在当前GUI线程之外的另一个线程中执行。

Pixmap

QPixmap类是一个屏幕外的图像表示,它被设计和优化为在屏幕上显示图像。与QImage不同,像素图中的像素数据是内部的,由底层窗口系统管理,即像素只能通过QPainter函数或将QPixmap转换为QImage来访问。
为了使用QPixmap优化绘图,Qt提供了QPixmapCache类,它可以用于存储生成昂贵的临时像素图,而不会使用超过缓存限制的存储空间。
Qt还提供了QBitmap便利类,继承了QPixmapQBitmap保证单色(1位深度)像素图,主要用于创建自定义QCursorQBrush对象,构造QRegion对象。

OpenGL绘制设备

如前所述,Qt提供了一些类,使在Qt应用程序中使用OpenGL变得很容易。例如,QOpenGLPaintDevice启用OpenGL API来Picture
QPicture类是一个记录和回放QPainter命令的绘图设备。图片以平台无关的格式将画工命令序列化到IO设备。QPicture也是独立于分辨率的,即一个QPicture可以显示在不同的设备上(例如svg, pdf, ps,打印机和屏幕),看起来是一样的。
Qt提供了QPicture::load()QPicture::save()函数以及用于加载和保存图片的流操作符。

Custom Backends

可以通过派生QPaintDevice类并重新实现虚拟QPaintDevice:: paintenengine()函数来实现对新后端的支持,以告诉QPainter应该使用哪个绘制引擎在这个特定的设备上绘制。要真正能够在设备上绘图,这个绘图引擎必须是从qpaintenengine类派生出来的自定义绘图引擎。

绘制

QPainter提供了高度优化的功能,以完成大多数绘图GUI程序所需的功能。它可以绘制从简单的图形基元(由QPoint, QLine, QRect, QRegion和QPolygon类表示)到复杂形状(如矢量路径)的一切。在Qt矢量路径是由QPainterPath类表示的。QPainterPath为绘制操作提供了一个容器,使图形形状能够被构造和重用。

QPainterPath

painter路径是由线条和曲线组成的对象。例如,矩形由直线组成,椭圆由曲线组成。
与普通绘图操作相比,绘制路径的主要优势在于,复杂的形状只需要创建一次;然后只需调用QPainter::drawPath()函数就可以多次绘制它们。
QPainterPath对象可用于填充、勾勒和裁剪。要为给定的painter路径生成可填充的轮廓,可以使用QPainterPathStroker类。
线条和轮廓是使用QPen类绘制的。pen由其样式(即线条类型)、宽度、笔刷、如何绘制端点(cap-style)以及如何绘制两条连接线之间的连接(join-style)来定义。pen的笔刷是一个QBrush对象,用来填充pen生成的笔画,也就是说,QBrush类定义了填充模式。
QPainter还可以绘制对齐的文本和像素图。
绘制文本时,使用QFont类指定字体。Qt将使用具有指定属性的字体,或者如果没有匹配的字体存在,Qt将使用最接近匹配的已安装字体。实际使用的字体属性可以使用QFontInfo类检索。此外,QFontMetrics类提供字体度量,QFontDatabase类提供有关底层窗口系统中可用字体的信息。
通常,QPainter在“自然”坐标系中绘制,但它能够使用QTransform类执行视图和世界坐标系转换。

反锯齿绘制

绘制时,像素渲染由QPainter::Antialiasing渲染提示控制。QPainter::RenderHint枚举用于指定QPainter的标志,这些标志可能被任何给定的引擎尊重,也可能不被尊重。
QPainter::Antialiasing值表示引擎应该尽可能地消除原语的边缘,即通过使用不同的颜色强度平滑边缘。

基本图形绘制、填充

绘制线

void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter p(this);
    p.drawLine(50, 50, 100, 150);
}

在这里插入图片描述
或者,创建时不指定绘制设备,在begin()函数中设置,end时结束绘制。

    QPainter p;
    p.begin(this);
    p.drawLine(50, 50, 100, 150);
    p.end();

绘制圆弧
绘制由给定矩形、startAngle和spanAngle定义的圆弧。
起始角和伸缩角必须以1/16度指定,即一个完整的圆等于5760(16 * 360)。角度的正值表示逆时针方向,负值表示顺时针方向。零度在3点钟方位。

    QPainter p;
    p.begin(this);
    QRectF rectangle(10.0, 20.0, 80.0, 60.0);
    int startAngle = 30 * 16;
    int spanAngle = 120 * 16;
    p.drawArc(rectangle, startAngle, spanAngle);
    p.end();

在这里插入图片描述
绘制弦
绘制由给定矩形、startAngle和spanAngle定义的弦。弦被当前的笔刷()填充。
起始角和伸缩角必须以1/16度指定,即一个完整的圆等于5760(16 * 360)。角度的正值表示逆时针方向,负值表示顺时针方向。零度在3点钟方位。

    QPainter p;
    p.begin(this);
    QRectF rectangle(10.0, 20.0, 80.0, 60.0);
    int startAngle = 30 * 16;
    int spanAngle = 120 * 16;
    p.drawChord(rectangle, startAngle, spanAngle);
    p.end();

在这里插入图片描述
绘制凸多边形

    QPainter p;
    p.begin(this);
    static const QPointF points[4] = {
        QPointF(40.0, 110.0),
        QPointF(50.0, 40.0),
        QPointF(110.0, 70.0),
        QPointF(120.0, 100.0)
    };
    p.drawConvexPolygon(points, 4);
    p.end();

在这里插入图片描述
绘制椭圆

    QPainter p;
    p.begin(this);
    QRectF rectangle(100.0, 50.0, 80.0, 60.0);

    p.drawEllipse(rectangle);
    p.end();

在这里插入图片描述
如果宽,高一样,就是圆。
绘制扇形

    QPainter p;
    p.begin(this);
    QRectF rectangle(100.0, 50.0, 160.0, 120.0);
    int startAngle = 30 * 16;
    int spanAngle = 120 * 16;

    p.drawPie(rectangle, startAngle, spanAngle);
    p.end();

在这里插入图片描述

填充

除此之外,还可以使用画笔及画刷进行绘制和填充
绘制多边形

    QPainter p;
    p.begin(this);
    QPen pen(QBrush(Qt::gray), 2, Qt::DashLine, Qt::FlatCap, Qt::RoundJoin);
    p.setPen(pen);

    p.setBrush(Qt::green);

    static const QPointF points[4] = {
        QPointF(40.0, 110.0),
        QPointF(50.0, 40.0),
        QPointF(110.0, 70.0),
        QPointF(120.0, 100.0)
    };
    p.drawPolygon(points, 4);
    p.end();

在这里插入图片描述
绘制圆角矩形

    QPainter p;
    p.begin(this);
    QPen pen(QBrush(Qt::black), 2, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin);
    p.setPen(pen);

    p.setBrush(Qt::lightGray);

    QRectF rectangle(10.0, 20.0, 80.0, 60.0);

    p.drawRoundedRect(rectangle, 20.0, 15.0);
    p.end();

在这里插入图片描述

渐变填充

使用画刷还可以进行渐变填充。
渐变有三种:

  • 线性渐变:QLinearGradient
  • 辐射渐变:QRadialGradient
  • 锥形渐变:QConicalGradient

在这里插入图片描述
绘制矩形

    QPainter p;
    p.begin(this);
    QPen pen(QBrush(Qt::black), 2, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin);
    p.setPen(pen);

    QLinearGradient linearGrad(QPointF(100, 100), QPointF(200, 200));
    linearGrad.setColorAt(0, Qt::black);
    linearGrad.setColorAt(1, Qt::white);
    p.setBrush(linearGrad);

    QRectF rectangle(100.0, 100.0, 100.0, 100.0);

    p.drawRoundedRect(rectangle, 20.0, 15.0);
    p.end();

在这里插入图片描述

结论

人生就是这样,有欢笑也有泪水。一部分人主要负责欢笑,另一部分人主要负责泪水

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1305278.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android : XUI- SimpleImageBanner+BannerItem带标题的轮播图-简单应用

示例图: 1.导入XUI http://t.csdnimg.cn/qgGaN 2.MainActivity.java package com.example.viewpagerbanne;import android.os.Bundle; import android.view.View; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.xu…

vue项目中 CDN 是vue本身的依赖可以按需加载还是项目中所有的第三方库都可以按需加载?

这是我看到CDN简介时产生的问题 相信很多小伙伴会有 和我一样的疑问 在这里 我也统一回答一下 CDN(内容分发网络)是一种通过将数据分发到全球各个节点,以提供快速、可靠的内容传输的技术。在Vue项目中,CDN可以用于按需加载Vue本…

Linux--操作系统

1. 常见的操作系统 Windowsmac OSLinuxiOSAndroid 2. 操作系统的定义 操作系统直接运行在计算机上的系统软件, 它是控制硬件和支持软件运行的计算机程序。 3. 操作系统的作用 向下控制硬件向上支持软件的运行,具有承上启下的作用。 4.总结 操作系统…

Server check fail, please check server xxx.xxx.xxx.xxx,port 9848 is available

记录一次服务调用中的错误 背景:我使用了nacos2.x的版本,同时在同一台服务器的三个docker容器中部署了nacos1、2、3,并将它们连接到了同一个docker网络 错误:Server check fail, please check server xxx.xxx.xxx.xxx,port 9848 …

事件驱动架构 vs. RESTful架构:通信模式对比与选择

1. 通信风格 事件驱动架构(EDA) 是一种异步通信风格,组件之间通过产生和消费事件进行通信。 事件是表示系统中重大变化或事件的消息,并分发给感兴趣的组件。这种通信模型允许系统的不同部分之间进行解耦和动态交互。 组件充当事件…

MTK Android P Sensor架构(一)

需求场景: 本来如果只是给传感器写个驱动并提供能读取温湿度数据的节点,是一件比较轻松的事情,但是最近上层应用的同事要求我们按照安卓标准的流程来,这样他们就能通过注册一个服务直接读取传感器事件数据了。这样做的好处就是第…

从手工测试进阶中高级测试?如何突破职业瓶颈...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 1、手工测试如何进…

【教3妹学编程-算法题】需要添加的硬币的最小数量

3妹:2哥2哥,你有没有看到新闻, 有人中了2.2亿彩票大奖! 2哥 : 看到了,2.2亿啊, 一生一世也花不完。 3妹:为啥我就中不了呢,不开心呀不开心。 2哥 : 得了吧,你又不买彩票&…

Vue 双向绑定:让数据与视图互动的魔法!(上)

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

人体关键点检测3:Android实现人体关键点检测(人体姿势估计)含源码 可实时检测

目录 1. 前言 2.人体关键点检测方法 (1)Top-Down(自上而下)方法 (2)Bottom-Up(自下而上)方法: 3.人体关键点检测模型训练 4.人体关键点检测模型Android部署 (1) 将Pytorch模型转换ONNX模型 (2) 将ONNX模型转换…

【JVM从入门到实战】(一) 字节码文件

一、什么是JVM JVM 全称是 Java Virtual Machine,中文译名 Java虚拟机。 JVM 本质上是一个运行在计算机上的程序,他的职责是运行Java字节码文件。 二、JVM的功能 解释和运行 对字节码文件中的指令,实时的解释成机器码,让计算机…

图论——二分图

图论——二分图 二分图通俗解释 有一个图,将顶点分成两类,边只存在不同类顶点之间,同类顶点之间设有边。称图 G 为二部图,或称二分图,也称欧图。 性质 二分图不含有奇数环图中没有奇数环,一定可以转换为二…

005、Softmax损失

之——softmax与交叉熵 杂谈 我们常用到softmax函数与交叉熵的结合作为损失函数以监督学习,这里做一个小小的总结。 正文 1.softmax的基本改进 所谓softmax就是在对接全连接层输出时候把输出概率归一化,最基础的就是这样: 效果就是这样&…

图文教程:stable-diffusion的基本使用教程 txt2img(多图)

之前我介绍了SD的安装过程,那么这篇将介绍怎么使用SD 使用模型 SD安装好之后,我们只有一个默认的模型。这个模型很难满足我们的绘图需求,那么有2种方法。 1是自己训练一个模型(有门槛)2是去网站上找一个别人练好的模…

算法通关村第四关—表达式问题(黄金)

表达式问题 一、计算器问题 计算器也是非常常见的问题,我们看一个中等问题。LeetCode227.给你一个字符串表达式s,请你实现一个基本计算器来计算并返回它的值。整数除法仅保留整数部分。  你可以假设给定的表达式总是有效的。所有中间结果将在[-231,231…

关于Anaconda的安装和环境部署(此章专为新手制定)

目录 Anaconda简介 一、软件下载(地址👇) 2:点击下载 3:版本选择: 4:Anaconda的安装包就下载完成了 2:恭喜你,看到这里已经完成安装了 三、部署环境 1&#xff1…

Vue 双向绑定:让数据与视图互动的魔法!(下)

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

Wireshark中的http协议包分析

Wireshark可以跟踪网络协议的通讯过程,本节通过http协议,在了解Wireshark使用的基础上,重温http协议的通讯过程。 TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于 字节流…

FastAPI之响应模型

前言 响应模型我认为最主要的作用就是在自动化文档的显示时,可以直接给查看文档的小伙伴显示返回的数据格式。对于后端开发的伙伴来说,其编码的实际意义不大,但是为了可以不用再额外的提供文档,我们只需要添加一个 response_mod…

scala变量与变量类型

1.6 变量与类型(重点)1.6.1 变量推断1.6.2 多变量定义1.6.3 var和val的区别 1.6.3.1 是否可变 1.6.3.2 延迟加载 1.6 变量与类型(重点) val修饰的变量,相当于Java中final修饰的变量; // 定义常量s1,使用…