重学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();
}
相关推荐
小短腿的代码世界1 天前
Qt Bluetooth源码深度解析:从HCI协议到跨平台API的完整架构
开发语言·qt·架构
小短腿的代码世界1 天前
Qt WebEngine多进程架构与IPC通信:从Chromium多进程到Qt信号槽融合
qt·架构·系统架构
尘中远1 天前
【Qwt 7.0 系列】快速入门与核心新特性概览 —— 更现代的 Qt 数据可视化库
qt·数据可视化·绘图·qwt·科学绘图
初阳7851 天前
【Qt】系统相关(3)——多线程
qt
初阳7851 天前
【Qt】系统相关(2)——文件
开发语言·qt
尘中远2 天前
【Qwt 7.0 系列】坐标轴与刻度系统 —— 刻度引擎、网格、图例与刻度朝内
qt·数据可视化·qcustomplot·qwt·工业软件·科学绘图
sycmancia2 天前
Qt——多线程间的互斥
开发语言·qt
尘中远2 天前
【Qwt 7.0 系列】常用图表类型实战 —— 柱状图、散点图、箱线图与直方图
qt·qwt·工业软件·科学绘图
尘中远2 天前
【Qwt 7.0 系列】交互功能详解 —— 平移、缩放、坐标轴交互与数据拾取
qt·数据可视化·绘图·qcustomplot·qwt·科学绘图
sycmancia2 天前
Qt——进程与线程的概念
qt