重学Qt——绘图

绘图

绘图系统

Qt的二维绘图功能

  • 主要使用QPainter进行绘图。
  • 绘图设备包括QWidget、QPixmap、QPrinter等。

QWidget作为最常见的绘图设备

  • QWidget是所有界面组件的基础。
  • 界面组件的显示效果是通过QPainter在QWidget上实现。
  • QPainter可以在QWidget上绘制自定义组件形状和实现特定显示效果,这是设计自定义界面组件的基础。

Qt的图形/视图架构

  • 通过使用QGraphicsView、QGraphicsScene和各种QGraphicsItem类来构建一个图形场景。
  • 可以在一个场景中绘制大量的图形项。
  • 每个图形项都是可选择、可交互操作的。

QPainter绘图系统

QPainter 是 Qt 框架中的一个类,用于在各种绘图设备上绘制基本图形。

  • 可以用于组件的显示效果,并支持绘制点、直线、圆、矩形、文字和位图,可以组合成复杂的图形。

绘图设备

QPaintDevice

  • 所有绘图设备的基类,无父类。

QWidget

  • 所有界面组件的基类,最常见的绘图设备类。
  • 继承自 QPaintDevice 和 QObject,支持 Qt 的元对象系统。

图片相关类

QImage:

  • 与硬件无关,用于设备输入输出。
  • 支持直接访问和操作图片像素数据。

QPixmap:

  • 为屏幕显示图片优化。

QBitmap:

  • QPixmap 的子类,用于表示单色位图。

QPicture:

  • 记录和回放 QPainter 指令。

矢量图形与渲染

QSvgGenerator

  • 创建 SVG 图形。
  • 可以将绘图内容保存为 SVG 文件。

QSvgWidget

  • 显示 SVG 图片文件的组件类。

QOpenGLPaintDevice

  • 使用 OpenGL 渲染 QPainter 绘图指令。
  • 需要系统支持 OpenGL 2.0 以上版本。

打印与文件输出

QPagedPaintDevice:

  • 支持多个页面,适用于打印输出和 PDF 文件生成。

QPrinter:

  • 用于打印输出,在设备上绘图以生成打印页面。

QPdfWriter:

  • 生成 PDF 文件的设备类。
  • 与 QPrinter 配合使用可保存为 PDF 文件。

QWidget绘图事件和绘图区

QWidget类有一个事件处理函数paintEvent(),在组件界面需要重绘时,系统会自动运行这个函数。

要在界面上绘图,我们需要在此事件处理函数里创建一个QPainter对象来获取绘图设备的接口,然后用这个QPainter对象在绘图设备上绘图。在事件处理函数paintEvent()里绘图的基本程

QGraphicsView

QPainter绘图的特性控制

  • QPen
  • QBrush
  • QPainter
QPen
QBrush
QPainter
cpp 复制代码
// 自定义仪表盘控件
class Speedometer : public QWidget {
protected:
    void paintEvent(QPaintEvent *) override {
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing); // 抗锯齿
        
        // 1. 绘制背景圆盘
        painter.setBrush(Qt::black);
        painter.drawEllipse(10, 10, width()-20, height()-20);
        
        // 2. 绘制刻度)
        painter.setPen(QPen(Qt::white, 3));
        for (int i = 0; i < 4; ++i) {
            painter.drawLine(50 + i*50, 80, 50 + i*50, 100);
        }
        
        // 3. 绘制指针
        painter.save(); // 保存状态
        painter.translate(width()/2, height()/2); // 移动到中心
        painter.rotate(80); // 根据车速旋转角度
        painter.setPen(QPen(Qt::red, 4));
        painter.drawLine(0, 0, 60, 0); // 画指针
        painter.restore(); // 恢复状态
    }
};

坐标系统和坐标变换

QPainter在绘图设备上绘图时默认使用设备的物理坐标。

QPainter提供了一些接口函数可以进行平移、旋转、缩放等坐标变换,还可以在绘图设备上定义视口坐标和窗口坐标。

窗口坐标是逻辑坐标,使用QPainter在逻辑坐标系中绘图,可以自动适应绘图区大小的变化。

坐标系统

坐标系统扮演着核心角色,使得图形绘制变得灵活和有效。下面是Qt绘图中的坐标系统的主要概念:

坐标系概述

  • 物理坐标系:指的是绘图设备的像素级坐标,通常与设备的实际分辨率相对应。
  • 逻辑坐标系:一个抽象的坐标系统,用于在更高层次上进行绘图,允许根据需求自动适应不同的绘图区大小。

坐标转换

Qt提供了一些坐标转换功能,主要包括:

  • 平移:可以通过translate()函数移动原点位置。
  • 缩放:通过scale()函数调整绘图的大小,改变坐标的比例。
  • 旋转:使用rotate()函数可以围绕原点旋转坐标系,使得图形相应旋转。

QPainter提供了一些坐标变换功能

函数名 功能描述
translate(qreal dx, qreal dy) 平移图形或坐标轴。
rotate(qreal angle) 旋转图形或坐标轴。
scale(qreal sx, qreal sy) 缩放图形或坐标轴。
shear(qreal sh, qreal sv) 对图形进行斜切变换。
save() 保存当前的图形状态(包括变换矩阵等)。常用于变换操作之前保存原始状态,以便之后恢复。
restore() 恢复之前保存的图形状态。常与save()配合使用,用于撤销之前的变换操作。
resetTransform() 重置图形状态到默认状态(通常是初始状态,无变换)。

视口和窗口

  • 视口(Viewport):指当前绘图设备的显示区域。可以通过setViewport()定义。
  • 窗口(Window):逻辑坐标系中的一个区域,通过setWindow()定义。逻辑坐标将在这个窗口内进行绘制。

逻辑坐标绘图

  • 使用逻辑坐标绘图时,可以实现自动适应绘图区大小的特性,使得图形能够在不同的窗口大小下保持比例和位置。

QPainter的使用

  • 在 QPainter 对象上,通常可以通过以下步骤设置坐标系统:
    1. 创建QPainter对象。
    2. 设置视口和窗口坐标。
    3. 进行绘图操作。
视口和窗口

视口和窗口的定义

绘图设备的物理坐标系是基本的坐标系,通过QPainter 的平移、旋转等坐标变换可以得到更容易操作的逻辑坐标系。

物理坐标系也称为视口(viewport)坐标系,逻辑坐标系也称为窗口( window)坐标系,通过内部的坐标变换矩阵,

QPainter 能自动将逻辑坐标变换为绘图设备的物理坐标。

图形/视图架构

一、QPainter绘图方法

  1. 概述
    • QPainter是Qt中用于绘图的核心类,它提供了一套丰富的绘图API。
    • 使用QPainter绘图时,通常需要在绘图设备(如QWidget或QGraphicsView等)的事件处理函数paintEvent()中编写绘图代码。
    • 通过QPainter绘制的图形是位图,即图像由像素点组成,放大或缩小时可能会失真。
  2. 使用场景
    • 适用于简单的图形绘制,如绘制线条、矩形、圆形等基础图形。
    • 适用于需要快速绘制且对图形质量要求不高的情况。

二、图形/视图架构

  1. 概述
    • Qt提供了图形/视图(graphics/view)架构,这是一种基于图形项(graphics item)的模型/视图结构。
    • 图形/视图架构允许开发者绘制复杂的图形,这些图形由成千上万个基本图形组件组成,并且每个图形组件都是可选择、可拖放和可修改的。
    • 与QPainter绘图不同,图形/视图架构绘制的图形是矢量图,即图形由几何形状和颜色等属性描述,放大或缩小时不会失真。
  2. 核心组件 :图形/视图架构主要由3个部分组成:
    • 图形项(Graphics Item):代表图形的基本组件,如线条、矩形、圆形等。每个图形项都是独立的,可以拥有自己的属性(如位置、大小、颜色等)和行为(如响应鼠标事件、动画等)。
    • 视图(View):用于显示图形项的场景。视图可以嵌入到QWidget中,作为用户界面的一部分。
    • 场景(Scene):作为图形项的容器,管理所有图形项的位置、大小、可见性等属性。场景可以包含多个图形项,并且支持图形项的添加、删除、移动等操作。
  3. 使用场景
    • 适用于需要绘制复杂图形且图形组件需要交互的情况,如矢量绘图软件、图形编辑器、游戏界面等。
    • 允许用户通过拖放、选择、修改等操作与图形进行交互,提高用户体验。

图形/视图架构的坐标系

在Qt的图形/视图架构中,坐标系的使用是设计和实现交互式图形界面的核心。以下是这套架构的主要坐标系介绍:

场景坐标系(Scene Coordinates)

  • 定义:场景坐标系是整个QGraphicsScene使用的坐标系统。
  • 特点:所有添加到场景中的项(QGraphicsItem)都以此坐标系进行定位。场景坐标是绝对的,可以用来准确表示图形项的位置和大小。

视口坐标系(Viewport Coordinates)

  • 定义:视口坐标系对应于QGraphicsView的可视区域。
  • 特点:视口坐标是相对的,局限于QGraphicsView的显示区域。它可以通过平移和缩放与场景坐标系进行转换。
  • 使用:在视口坐标系中,用户交互(例如鼠标事件)和绘制都是基于这个坐标系统进行的。

逻辑坐标系(Logical Coordinates)

  • 定义:是用于在场景中绘图的逻辑坐标。用户可以在这个坐标系中设计和布局图形项,而不必关心其在具体视口中的表现。
  • 特点:逻辑坐标可以随着视图的缩放和移动进行调整,这使得图形项能够在不同显示条件下保持相对位置。

坐标变换

  • 平移:可以通过QGraphicsView的变换功能来移动场景的视图,影响视口坐标系中的项的位置。
  • 缩放:视口也支持缩放操作,通过scale()函数,可以改变视口显示内容的比例,而场景的逻辑坐标仍保持不变。
  • 旋转:视图也支持旋转变换,这会影响视口中的项的显示角度。

转换关系

  • Qt提供了一系列函数,例如mapToScene()和mapFromScene(),用于在视口坐标和场景坐标之间转换。这使得事件处理和绘图操作能够有效地在不同坐标系之间切换。

图像处理

QImage和 QPixmap是用于图像显示和处理的绘图设备类。

图片基础

一、颜色数据格式

  1. 概述
    • 图像的显示基于每个像素的颜色数据。
    • 颜色数据有多种表示格式,常见的有RGB32、RGB888、ARGB32、RGBA32、RGB565和灰度等。
  2. 具体格式说明
    • RGB32:使用32位无符号整数表示,实际用24位有效数据表示颜色,常用于计算机上存储的图片文件。
    • RGB888:红色、绿色、蓝色各用1字节表示,共占3字节,但非标准整数类型,常在内存有限的系统中使用。
    • ARGB32和RGBA32:在RGB基础上加入Alpha值表示不透明度。
    • RGB565:用16位无符号整数表示,适用于嵌入式设备的TFT-LCD,可节省存储空间。
    • Grayscale8和Grayscale16:用于表示灰度颜色的8位和16位无符号整数。

二、图片文件格式

  1. BMP格式
    • 位图文件格式,存储图像的宽度、高度、颜色数据等。
    • 像素颜色数据无修改地保存在文件中,如RGB32数据。
    • BMP是无损图片文件格式,文件较大。
  2. JPG格式
    • 使用JPEG压缩算法的有损压缩格式。
    • 可减小文件大小,节省存储空间,但有一定图像质量损失。
    • BMP图片文件转换为JPG后,JPG文件大小通常只有BMP的约10%。
  3. PNG格式
    • 无损压缩图片文件格式,具有一定压缩率。
    • 文件解压后为真实原图,支持Alpha通道,如ARGB32颜色数据。
  4. SVG格式
    • 基于XML的矢量图文件格式,不存储像素颜色数据,而是描述图像绘制方法。
    • 不能用QImage和QPixmap类处理,需使用QSvgRenderer和QSvgWidget类读取和显示。

QImage

QImage 是 Qt 图形模块中的一个类,主要用于处理和存储图像数据。它提供了多种功能,包括图像加载、保存、绘制和操作,是 Qt 图形应用中的重要组件。

主要特性

  1. 多种格式支持
    • 支持多种图像格式,如 PNG、JPEG、BMP 等。
  2. 图像操作
    • 提供丰富的图像处理功能,如缩放、旋转、裁剪、颜色转换等。
  3. 直接访问像素
    • 可直接操作图像的像素数据,支持高效的图像处理。
  4. 与 QPainter 兼容
    • 可以与 QPainter 类结合使用,将图像绘制到窗口或其他图形设备上。

常用方法

  • 加载和保存图像
cpp 复制代码
QImage image;
image.load("image.png");
image.save("output.jpg");
  • 访问像素
cpp 复制代码
QRgb pixel = image.pixel(x, y); // 获取像素颜色
image.setPixel(x, y, qRgb(255, 0, 0)); // 设置像素颜色为红色
  • 图像转换
cpp 复制代码
QImage scaledImage = image.scaled(100, 100, Qt::KeepAspectRatio);
  • 绘制图像
cpp 复制代码
QPainter painter(this);
painter.drawImage(0, 0, image);

示例:如何使用 QImage 加载、处理和绘制图像。

cpp 复制代码
#include <QApplication>
#include <QWidget>
#include <QImage>
#include <QPainter>

class ImageWidget : public QWidget {
protected:
    void paintEvent(QPaintEvent *) override {
        QImage image("example.png"); // 加载图像
        if (!image.isNull()) {
            QPainter painter(this);
            painter.drawImage(0, 0, image.scaled(size(), Qt::KeepAspectRatio)); // 绘制缩放后的图像
        }
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    
    ImageWidget w;
    w.resize(800, 600);
    w.setWindowTitle("QImage Example");
    w.show();
    
    return app.exec();
}
相关推荐
森G14 小时前
61、信号与槽机制在 TCP 编程中的应用---------网络编程
网络·c++·qt·网络协议·tcp/ip
古德new15 小时前
鸿蒙PC迁移:Photoflare Qt 图片编辑器鸿蒙PC适配全记录
qt·编辑器·harmonyos
古德new20 小时前
鸿蒙PC迁移:Anki Qt 记忆卡片工具鸿蒙PC适配全记录
qt·华为·harmonyos
雪的季节21 小时前
Qt 进程间通信(IPC)全方案
qt
雪的季节1 天前
Qt Graphs 2D+3D介绍
qt·3d
小鹏linux1 天前
鸿蒙PC迁移:TupiTube Desk Qt 2D 动画工作室鸿蒙PC适配全记录
qt·华为·harmonyos
鸽芷咕1 天前
鸿蒙PC迁移:LANDrop Qt 局域网传输工具鸿蒙PC适配全记录
qt·华为·harmonyos
Lhan.zzZ1 天前
Qt Quick 嵌套 Dialog 与 ComboBox 层级混乱问题解决
c++·qt
森G1 天前
67、Qt 多媒体框架概述---------多媒体
开发语言·qt
鸽芷咕1 天前
鸿蒙PC迁移:MoonPlayer Qt 视频播放器鸿蒙PC适配全记录
qt·音视频·harmonyos