QtGUI模块功能详细说明,窗口和屏幕管理(一)

目录

一. 窗口和屏幕管理

1、核心抽象与基础

1.1、Qt 图形栈中的窗口与屏幕管理

1.2、QGuiApplication:GUI 应用程序的核心

1.3、QScreen:访问和管理屏幕信息

2、QWindow:顶层窗口的抽象

2.1、QWindow 的基本概念与创建

2.2、QWindow 的几何管理

2.3、QWindow 的事件处理

2.4、QWindow 与本地窗口系统的交互

3、渲染与显示

3.1、QSurface 和 QSurfaceFormat:定义渲染表面

3.2、QBackingStore:高效的像素缓冲区管理

3.3、 QOffscreenSurface:离屏渲染

4、高级主题

4.1、自定义窗口框架 (基于 QWindow)

4.2、透明和半透明窗口 (基于 QWindow)

二. 绘图和渲染

三. 图像处理

四. 字体和文本

五. 事件和输入处理

六. OpenGL 和硬件加速

七. 颜色和外观

八. 图标和光标

九. 平台和渲染后端

十. 国际化(GUI 相关)


一. 窗口和屏幕管理

1、核心抽象与基础

1.1、Qt 图形栈中的窗口与屏幕管理

Qt 是一个功能强大的跨平台 C++ 框架,广泛用于构建图形用户界面(GUI)和非 GUI 应用程序。其图形栈(Graphics Stack)是 Qt 的核心模块之一,负责管理窗口、屏幕、渲染表面以及跨平台图形渲染的抽象。

  • 窗口管理负责创建、显示和操作窗口;

  • 屏幕管理则提供对物理显示设备(如显示器)的访问和配置支持。

从 QGuiApplication 到渲染表面

  • QGuiApplication:GUI 应用程序的核心入口,负责初始化图形栈、管理事件循环、全局设置(如主题、输入法)和应用程序生命周期。

  • QWindow:表示一个顶级窗口或子窗口,负责窗口的创建、显示和用户交互。

  • QScreen:提供对物理屏幕的访问,包含屏幕的几何信息、分辨率、像素密度、方向等属性,支持多显示器场景。

  • QBackingStore:用于软件渲染的后台存储,管理窗口的像素数据,适用于非 OpenGL 的渲染路径。

  • QSurface:抽象的渲染表面,QWindow 和 QOffscreenSurface 都继承自 QSurface,表示可以渲染的内容区域。

  • QSurfaceFormat:定义渲染表面的格式,如颜色深度、缓冲区配置、OpenGL 版本等。

  • QOffscreenSurface:离屏渲染表面,用于在非窗口场景下进行图形渲染(如生成纹理或图像)。

1.2、QGuiApplication:GUI 应用程序的核心

QGuiApplication 是单例类,可以通过 QGuiApplication::instance() 获取当前实例,确保 QGuiApplication已创建,否则返回nullptr。

1.2.1、应用程序生命周期管理和事件循环

  • 生命周期:

    • 构造:创建 QGuiApplication 实例,通常传递命令行参数(argc 和 argv)。

    • 初始化:初始化平台相关的图形资源(如 OpenGL 上下文、窗口系统)。

    • 运行:调用 exec() 启动事件循环,处理用户输入、定时器和窗口事件。

    • 退出:调用 quit() 或 exit() 结束应用程序,释放资源。

  • 事件循环:

    • QGuiApplication 维护一个事件循环,负责分发事件(如鼠标点击、键盘输入、窗口重绘)。

    • 事件循环通过 QEventLoop 实现,支持异步操作和信号槽机制。

    • 开发者可以通过 processEvents() 手动处理挂起的事件。

1.2.2、全局设置与配置

  • 主题和样式:通过 setStyle() 或 setPalette() 设置应用程序的外观。

  • 光标:通过 setOverrideCursor() 全局修改鼠标光标。

  • 输入法:支持跨平台的输入法管理(如中文输入法),通过 QInputMethod 访问。

  • 字体:通过 setFont() 设置全局字体。

  • 高 DPI 支持:通过 setHighDpiScaleFactorRoundingPolicy() 配置高 DPI 缩放策略

1.2.3、信号与槽机制在应用程序管理中的应用

  • screenAdded(QScreen*):新屏幕连接时触发。

  • screenRemoved(QScreen*):屏幕断开时触发。

  • focusWindowChanged(QWindow*):窗口获得或失去焦点时触发。

  • applicationStateChanged(Qt::ApplicationState):应用程序状态(如前台、后台)变化时触发。

1.2.4、应用程序退出和状态管理

  • 退出:调用 quit() 或 exit(int returnCode) 终止应用程序。

  • 状态管理:

    • applicationState():返回当前状态(Qt::ApplicationActive,Qt::ApplicationSuspended)。

    • isSavingSession():检查是否正在保存会话(平台相关)。

1.3、QScreen:访问和管理屏幕信息

QScreen 类提供了对物理屏幕的访问,允许开发者获取屏幕的几何信息、分辨率、像素密度、方向等属性。它是多显示器支持和屏幕适配的核心类,适用于动态调整窗口布局和渲染内容。

  • QGuiApplication::screens():返回所有可用屏幕的 QScreen 指针列表。

  • QGuiApplication::primaryScreen():返回主屏幕的 QScreen 指针。

1.3.1、QScreen 对象的详细属性

  • geometry():返回屏幕的完整矩形(QRect),包括装饰边框(如窗口标题栏)。

  • availableGeometry():返回屏幕的可用区域(QRect),不包括任务栏、Dock 或其他系统 UI 元素。

  • physicalDotsPerInch():返回屏幕的物理 DPI(每英寸点数),反映硬件像素密度。

  • logicalDotsPerInch():返回逻辑 DPI,考虑了操作系统的缩放设置。

  • devicePixelRatio():返回逻辑像素与物理像素的比率(qreal),常用于高 DPI 屏幕。

  • orientation():返回屏幕的方向(Qt::ScreenOrientation)。

  •  orientationChanged(Qt::ScreenOrientation) 信号:可用于响应方向变化。

  • refreshRate():返回屏幕的刷新率(Hz),如 60Hz 或 120Hz。

  • colorSpace():返回屏幕支持的颜色空间(如 sRGB、Display P3)。

  • 多显示器支持,信号:

    • QGuiApplication::screenAdded(QScreen*)

    • QGuiApplication::screenRemoved(QScreen*)

    • QScreen::geometryChanged(QRect)

    • QScreen::physicalDotsPerInchChanged(qreal)

  • virtualGeometry():在多显示器场景下,Qt 支持访问虚拟桌面的整体几何信息.

2、QWindow:顶层窗口的抽象

QWindow 是 Qt 图形栈中表示顶层窗口或子窗口的核心类,提供了跨平台的窗口抽象。它是 Qt Quick 和基于 OpenGL/Vulkan 渲染的应用程序的基础,同时也支持软件渲染。QWindow 不仅负责窗口的创建和显示,还管理几何属性、用户交互事件以及与底层窗口系统的对接。

2.1、QWindow 的基本概念与创建

  • 跨平台抽象:QWindow 屏蔽了不同操作系统(如 Windows 的 HWND、Linux 的 X11 Window、macOS 的 NSWindow)的底层窗口实现,提供统一的接口。

  • 渲染载体:QWindow 是渲染表面的载体,支持 OpenGL、Vulkan、DirectX 或软件渲染。

  • 灵活性:支持顶层窗口(如主窗口)、子窗口(如嵌入式窗口)以及特殊窗口(如弹出菜单、工具提示)。

2.1.1、创建 QWindow 实例

  • QWindow 实例通过构造函数创建,默认构造一个空的顶层窗口。

  • 可选参数:指定父窗口(QWindow*)或关联的 QScreen。

  • 注意:创建 QWindow 后需调用 show() 使其可见。

2.1.2、设置窗口标题 (setTitle())

  • setTitle(const QString &):设置窗口的标题栏文本。

  • 标题通常显示在窗口的顶部(平台相关,可能被忽略,如无边框窗口)。

2.1.3、控制窗口可见性

  • show():显示窗口,使其可见。

  • hide():隐藏窗口,但不销毁。

  • showMaximized():最大化显示。

  • showMinimized():最小化显示。

  • showFullScreen():全屏显示。

2.1.4、关闭窗口,Qt6.0

  • close():关闭窗口,触发 QCloseEvent。

  • closeEvent(QCloseEvent*):虚函数,可重写以自定义关闭行为(如提示保存)。

2.1.5、代码样例

#include <QGuiApplication>
#include <QWindow>
#include <QCloseEvent>
#include <QDebug>

class MyWindow : public QWindow {
protected:
//===========Qt 6
//    void closeEvent(QCloseEvent *event) override {
//        // 提示用户确认关闭
//        qDebug() << "Window is about to close. Save changes?";
//        event->accept(); // 接受关闭
//        event->ignore(); // 忽略关闭
//    }

    //=============Qt5
    bool event(QEvent *event)
    {
        if (event->type() == QEvent::Close) {

            QCloseEvent *closeEvent = static_cast<QCloseEvent *>(event);
            qDebug() << "Window is about to close. Save changes?";
            return QWindow::event(closeEvent);  // 调用基类处理(很重要)
        }
        return QWindow::event(event); // 调用父类的事件处理
    }
};

int main(int argc, char *argv[]) {
    QGuiApplication app(argc, argv);
    MyWindow window;
    window.setTitle("My Qt Window");
    window.show(); //显示
    return app.exec();
}


2.2、QWindow 的几何管理

QWindow 提供了丰富的几何管理功能,用于控制窗口的位置、大小和状态。

2.2.1、设置和获取窗口的位置

  • 设置位置:

    • setX(int)、setY(int):设置窗口的 x 或 y 坐标(相对于屏幕左上角)。

    • setPosition(const QPoint &):设置窗口的左上角位置。

    • setPosition(int x, int y):同上,接受单独的 x 和 y 值。

  • 获取位置:

    • x()、y():返回窗口的 x 或 y 坐标。

    • position():返回窗口的左上角位置(QPoint)。

2.2.2、设置和获取窗口的大小

  • 设置大小:

    • setWidth(int)、setHeight(int):设置窗口的宽度或高度。

    • resize(const QSize &):设置窗口的大小。

  • 获取大小:

    • width()、height():返回窗口的宽度或高度。

    • size():返回窗口的大小(QSize)。

2.2.3、设置和获取窗口的几何矩形

  • setGeometry(const QRect &):设置窗口的位置和大小(包括 x, y, width, height)。

  • setGeometry(int x, int y, int w, int h):同上,接受单独的参数。

  • geometry():返回窗口的几何矩形(QRect),包括位置和大小。

  • 注意:geometry 包括窗口框架(标题栏等),实际内容区域可能通过 frameGeometry() 。

2.2.4、窗口状态控制

  • showMaximized():最大化窗口。

  • showMinimized():最小化窗口。

  • showFullScreen():全屏显示。

  • showNormal():恢复正常状态。

  • windowState():返回当前状态(Qt::WindowState)

  • setWindowState(Qt::WindowState):设置窗口状态。

2.2.5、窗口标志 (flags(), setFlags())

  • flags():返回当前窗口标志(Qt::WindowFlags)。

  • setFlags(Qt::WindowFlags):设置窗口标志,控制窗口的行为和外观。

  • 常用标志:

    • Qt::FramelessWindowHint:无边框窗口。

    • Qt::WindowStaysOnTopHint:窗口始终保持在顶部。

    • Qt::Tool:工具窗口(如弹出菜单)。

    • Qt::Dialog:对话框窗口。

    • Qt::WindowSystemMenuHint:显示系统菜单(平台相关)。

2.2.6、代码样例

#include <QGuiApplication>
#include <QWindow>
#include <QDebug>


int main(int argc, char *argv[]) {
    QGuiApplication app(argc, argv);
    QWindow window;
    window.setTitle("My Qt Window");

    window.setPosition(100, 100); // 移动到 (100, 100)
    qDebug() << "Position:" << window.position();

    window.setGeometry(100, 100, 800, 600);//几何设置
    qDebug() << "Geometry:" << window.geometry();

    window.frameGeometry();//内容区

    Qt::WindowStates state=   window.windowState();//状态
    qDebug()<<state<<endl;
    window.showMinimized();
    state=   window.windowState();
    qDebug()<<state<<endl;


    window.setFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);//窗口标识
    qDebug()<< window.flags()<<endl;


    window.show(); //显示

    return app.exec();
}


2.3、QWindow 的事件处理

QWindow 的事件处理机制基于 Qt 的事件系统,允许开发者捕获和响应用户交互、窗口状态变化等事件。

2.3.1、窗口事件类型 (QEvent)

  • 窗口事件:如暴露(QExposeEvent)、调整大小(QResizeEvent)、移动(QMoveEvent)、关闭(QCloseEvent)。

  • 输入事件:如鼠标(QMouseEvent)、键盘(QKeyEvent)、触摸(QTouchEvent)。

  • 焦点事件:如 QFocusInEvent、QFocusOutEvent。

  • 其他:如 QShowEvent、QHideEvent。

2.3.2、常见的窗口事件

  • 暴露事件 (QExposeEvent):

    • 当窗口的一部分或全部需要重绘时触发(如窗口显示或被遮挡区域重新暴露)。

    • 用途:触发渲染更新。

    • 属性:region() 返回需要重绘的区域。

  • 调整大小事件 (QResizeEvent):

    • 当窗口大小改变时触发。

    • 属性:size() 返回新大小,oldSize() 返回旧大小。

  • 移动事件 (QMoveEvent):

    • 当窗口位置改变时触发。

    • 属性:pos() 返回新位置,oldPos() 返回旧位置。

  • 关闭事件 (QCloseEvent):

    • 当窗口关闭时触发,可通过 accept() 或 ignore() 控制行为。

  • 焦点事件 (QFocusInEvent, QFocusOutEvent):

    • 当窗口获得或失去焦点时触发。

  • 输入事件:

    • 鼠标事件:QMouseEvent(点击、移动、滚轮)。

    • 键盘事件:QKeyEvent(按键按下、释放)。

    • 触摸事件:QTouchEvent(多点触控)。

2.3.3、重写事件处理函数

  • 通用事件处理:重写 event(QEvent*) 处理所有事件。

  • 特定事件处理:重写特定事件函数,如 resizeEvent()、exposeEvent()。

2.3.4、代码示例

#include <QGuiApplication>
#include <QWindow>
#include <QEvent>
#include <QExposeEvent>
#include <QResizeEvent>
#include <QMoveEvent>
#include <QCloseEvent>
#include <QFocusEvent>
#include <QMouseEvent>
#include <QKeyEvent>
#include <QTouchEvent>
#include <QDebug>
#include <QPainter>

class MyWindow : public QWindow
{
public:
    MyWindow() : QWindow() {
        setTitle("Event Test Window");
        setGeometry(100, 100, 400, 300);
        setMouseGrabEnabled(true); // 启用鼠标抓取,以便接收所有鼠标事件
    }

protected:
    bool event(QEvent *event) override {
        qDebug() << "Event Type:" << event->type();
        return QWindow::event(event); // 调用基类实现以确保默认行为
    }

    void exposeEvent(QExposeEvent *event) override {
        qDebug() << "Expose Event - Region:" << event->region();
    }

    void resizeEvent(QResizeEvent *event) override {
        qDebug() << "Resize Event - New Size:" << event->size() << ", Old Size:" << event->oldSize();
    }

    void moveEvent(QMoveEvent *event) override {
        qDebug() << "Move Event - New Position:" << event->pos() << ", Old Position:" << event->oldPos();
    }
//============Qt6
//    void closeEvent(QCloseEvent *event) override {
//        qDebug() << "Close Event - Accepting close";
//        event->accept(); // 允许窗口关闭
//        // event->ignore(); // 阻止窗口关闭
//    }

    void focusInEvent(QFocusEvent *event) override {
        qDebug() << "Focus In Event - Reason:" << event->reason();
    }

    void focusOutEvent(QFocusEvent *event) override {
        qDebug() << "Focus Out Event - Reason:" << event->reason();
    }

    void mousePressEvent(QMouseEvent *event) override {
        qDebug() << "Mouse Press Event - Button:" << event->button() << ", Position:" << event->pos();
    }

    void mouseReleaseEvent(QMouseEvent *event) override {
        qDebug() << "Mouse Release Event - Button:" << event->button() << ", Position:" << event->pos();
    }

    void mouseMoveEvent(QMouseEvent *event) override {
        qDebug() << "Mouse Move Event - Position:" << event->pos();
    }

    void keyPressEvent(QKeyEvent *event) override {
        qDebug() << "Key Press Event - Key:" << event->key() << ", Text:" << event->text();
    }

    void keyReleaseEvent(QKeyEvent *event) override {
        qDebug() << "Key Release Event - Key:" << event->key();
    }

    void touchEvent(QTouchEvent *event) override {
        qDebug() << "Touch Event - Points:" << event->touchPoints().count();
        for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
            qDebug() << "  Point ID:" << point.id() << ", Pos:" << point.pos() << ", State:" << point.state();
        }
        event->accept(); // 标记触摸事件已被处理
    }
};

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    MyWindow window;
    window.show();

    return app.exec();
}

2.4、QWindow 与本地窗口系统的交互

QWindow 通过与底层窗口系统的交互,提供跨平台一致性,同时允许开发者访问平台特定的功能。

2.4.1、窗口句柄 (winId()) 的获取和使用

  • winId():返回平台特定的窗口句柄(如 Windows 的 HWND、Linux 的 Window ID)。

  • 用途:与本地 API 交互(如调用 Windows API 设置窗口属性)。

2.4.2、窗口激活和焦点管理

  • requestActivate():请求激活窗口(使其成为前台窗口)。

  • 信号:

    • focusObjectChanged(QObject*):焦点对象变化时触发。

    • activeChanged():窗口激活状态变化时触发。

2.4.3、模态窗口的实现

  • 模态窗口:阻止用户与父窗口交互,直到模态窗口关闭。

  • 实现方式:

    • 设置窗口标志:Qt::Dialog 或 Qt::Popup。

    • 使用 setModality(Qt::WindowModality):

      • Qt::NonModal:非模态(默认)。

      • Qt::WindowModal:对父窗口模态。

      • Qt::ApplicationModal:对整个应用程序模态。

2.4.4、示例代码

#include <QGuiApplication>
#include <QWindow>
#include <QDebug>

int main(int argc, char *argv[]) {
    QGuiApplication app(argc, argv);
    QWindow parent;
    parent.setGeometry(100, 100, 800, 600);
    parent.show();

    QWindow dialog;
    dialog.setTitle("Modal Dialog");
    dialog.setGeometry(200, 200, 400, 300);
    dialog.setModality(Qt::ApplicationModal); // 设置为应用模态
    dialog.setFlags(Qt::Dialog);
    dialog.show();
    //窗口切换会触发
    QObject::connect(&dialog,&QWindow::activeChanged,[](){
        qDebug()<<"activeChanged"<<endl;
    });

    return app.exec();
}

3、渲染与显示

3.1、QSurface 和 QSurfaceFormat:定义渲染表面

3.1.1、 QSurface 作为抽象渲染表面的概念

QSurface 是 Qt 中用于表示渲染目标的抽象基类,提供了统一接口来描述可以进行渲染的表面,定义了表面的类型(如 RasterSurface、OpenGLSurface)和属性(如大小、格式)。

子类包括:

  • QWindow:表示屏幕上的窗口表面。

  • QOffscreenSurface:表示离屏渲染表面。

3.1.2、QSurfaceFormat 的作用

QSurfaceFormat 用于指定渲染表面的配置,包括颜色深度、缓冲区类型、OpenGL 特性等。它定义了渲染上下文的属性,适用于 OpenGL 或其他图形 API 的渲染。

使用场景:

  • 配置 QWindow 或 QOpenGLWidget 的渲染属性。

  • 确保渲染上下文满足特定图形 API 的需求(如 OpenGL 核心模式)。

主要属性:

  • 颜色缓冲区:setRedBufferSize()、setGreenBufferSize()、setBlueBufferSize()、setAlphaBufferSize() 用于设置 RGBA 通道的位深度。

  • 深度和模板缓冲区:setDepthBufferSize()、setStencilBufferSize() 用于 3D 渲染。

  • 交换缓冲区:setSwapBehavior() 控制双缓冲或三缓冲 QSurfaceFormat::DoubleBuffer。

  • OpenGL 特性:

    • setVersion(major, minor):指定 OpenGL 版本(如 3.3、4.5)。

    • setProfile():设置 OpenGL 上下文类型(如核心模式 CoreProfile 或兼容模式 CompatibilityProfile)。

    • setRenderableType():指定渲染 API(如 QSurfaceFormat::OpenGL、OpenGL_ES、Vulkan)。

  • 采样:setSamples() 设置多重采样抗锯齿(MSAA)的采样数。

  • 其他:如 setSwapInterval() 控制垂直同步(V-Sync)。

3.1.3 、为 QWindow 设置 QSurfaceFormat

  • 创建 QSurfaceFormat 对象并配置属性。

  • 设置 QWindow 的表面类型( QSurface::OpenGLSurface 或 QSurface::RasterSurface)

  • 应用 QSurfaceFormat。

  • 创建并显示窗口。

  • 必须在 QWindow::create() 之前设置 QSurfaceFormat,否则配置无效。

3.1.4、示例代码

#include <QGuiApplication>
#include <QWindow>
#include <QDebug>

int main(int argc, char *argv[]) {
    QGuiApplication app(argc, argv);

    QSurfaceFormat format;
    format.setVersion(3, 3); // 使用 OpenGL 3.3
    format.setProfile(QSurfaceFormat::CoreProfile); // 核心模式
    format.setDepthBufferSize(24); // 24 位深度缓冲
    format.setSamples(4); // 4x 多重采样
    format.setSwapInterval(1); // 开启垂直同步


    QWindow window;
    window.setSurfaceType(QSurface::OpenGLSurface); // 设置为 OpenGL 表面
    window.setFormat(format);//应用 QSurfaceFormat

    window.create();
    window.show();


    return app.exec();
}

3.2、QBackingStore:高效的像素缓冲区管理

QBackingStore 是一个用于光栅化渲染的像素缓冲区管理类,适用于 QWindow 的 2D 绘制

它提供了一个高效的后备缓冲区(backing store),用于存储窗口的像素数据,并在需要时将其呈现到屏幕。

作用:

  • 管理窗口的像素缓冲区,避免直接绘制到屏幕导致闪烁。

  • 支持高效的重绘机制,仅更新窗口的脏区域(dirty regions)。

  • 与 QPainter 配合,提供简单易用的 2D 绘制接口。

重要性:

  • 在非 OpenGL 的光栅化渲染场景中,QBackingStore 是 Qt 的核心组件。

  • 适合绘制复杂 UI、文本、图像等场景。

3.2.1、缓冲区的创建、调整和更新

  • 构造 QBackingStore 时,传入 QWindow 对象。

  • 当窗口大小改变时,调用 resize() 调整缓冲区大小。

  • 缓冲区内容通过绘制操作更新,仅在需要时更新脏区域以优化性能。

3.2.2、绘制到 QBackingStore

  • 调用 beginPaint() 开始绘制,传入需要更新的区域。

  • 获取绘制设备(paintDevice())并使用 QPainter 绘制。

  • 调用 endPaint() 结束绘制。

  • 绘制操作必须在 beginPaint() 和 endPaint() 之间完成。

  • paintDevice() 返回的设备是缓冲区的像素数据,不能直接用于屏幕显示。

3.2.3、将缓冲区内容呈现到屏幕

  • 调用 flush() 将缓冲区内容复制到窗口的指定区域。

  • 尽量限制 flush() 的区域,仅更新实际变化的部分(通过 QRegion 指定)。

3.2.4、优化渲染性能的策略

  • 使用 QRegion 指定脏区域,仅重绘变化部分,避免不必要的全窗口重绘。

  • 对于静态内容,使用 QImage 或 QPixmap 缓存绘制结果,减少重复绘制。

  • 如果平台支持(如 Windows 的 Direct2D),Qt 会自动使用硬件加速来优化 QBackingStore 的性能。

3.2.5、示例代码

#include <QGuiApplication>
#include <QWindow>
#include <QBackingStore>
#include <QPainter>
#include <QDebug>
#include <QExposeEvent>
#include <QResizeEvent>


// 创建一个继承自 QWindow 的自定义窗口类
class BackingStoreWindow : public QWindow
{
    Q_OBJECT

public:
    explicit BackingStoreWindow(QWindow *parent = nullptr)
        : QWindow(parent),
          m_backingStore(new QBackingStore(this))
    {
        // 设置窗口的表面类型为 RasterSurface,表明使用光栅化(CPU)渲染
        setSurfaceType(QWindow::RasterSurface);
    }

    ~BackingStoreWindow() override
    {
        delete m_backingStore;
    }

protected:

    // 处理窗口大小变化的事件
    void resizeEvent(QResizeEvent *event) override
    {
        Q_UNUSED(event);
        // 调整 BackingStore 的大小以匹配窗口的新尺寸
        m_backingStore->resize(size());
        // 窗口大小变化通常需要完全重绘
        paint(QRegion(0, 0, width(), height()));

    }

    // 核心绘制函数,接收需要绘制的区域
    void paint(const QRegion &region)
    {
        if (region.isEmpty()) {
            return;
        }

        // 1. 开始绘制到 BackingStore,指定需要更新的区域
        m_backingStore->beginPaint(region);

        // 2. 获取 BackingStore 的绘制设备,并创建 QPainter
        QPaintDevice *device = m_backingStore->paintDevice();
        QPainter painter(device);

        // 限制 QPainter 的绘制区域,只绘制脏区域,提高效率
        painter.setClipRegion(region);

        // 3. 执行绘制操作
        // 示例:填充背景
        painter.fillRect(region.boundingRect(), Qt::white);

        // 示例:绘制一个动态位置的矩形
        static int xOffset = 0;
        painter.setBrush(Qt::blue);
        painter.drawRect(50 + xOffset, 50, 100, 50);
        xOffset = (xOffset + 1) % 200; // 简单动画效果

        // 示例:绘制一些文本
        painter.setPen(Qt::black);
        painter.setFont(QFont("Arial", 20));
        painter.drawText(50, 150, "Hello, QBackingStore!");
        painter.drawText(50, 180, QString("Window Size: %1x%2").arg(width()).arg(height()));

        // 4. 结束绘制
        painter.end();

        // 5. 将 BackingStore 的内容呈现到屏幕
        // 将绘制的区域 flush 到窗口,使其可见
        m_backingStore->flush(region);

    }


private:
    QBackingStore *m_backingStore;

};


#include "main.moc"


int main(int argc, char *argv[])
{
    QGuiApplication a(argc, argv);

    BackingStoreWindow window;
    window.setTitle("QBackingStore Example");
    window.resize(400, 300);
    window.show();

    return a.exec();
}

3.3、 QOffscreenSurface:离屏渲染

QOffscreenSurface 是一个用于离屏渲染的表面,不直接显示在屏幕上,适合后台渲染任务。

应用场景:

  • 图像处理:在后台生成或处理图像(如缩放、滤镜)。

  • 纹理生成:为 OpenGL 或 Vulkan 生成纹理数据。

  • 测试渲染:在不显示窗口的情况下测试渲染代码。

  • 截图或导出:将渲染结果保存为图像文件。

3.3.1、创建和配置 QOffscreenSurface

  • 构造 QOffscreenSurface 并设置其格式。

  • 设置大小(通过 setSize() 或 QSurfaceFormat 的默认大小)。

  • 确保 create() 调用成功(检查 surface.isValid())。

3.3.2、结合 QPainter 或其他渲染 API 进行离屏绘制

  • 使用 QPainter:创建 QImage 作为渲染目标,结合 QPainter 绘制。

  • 使用 OpenGL:创建 OpenGL 上下文并绑定到 QOffscreenSurface。

3.3.3、获取渲染结果

  • 保存为图像:

    • 如果使用 QImage,直接保存。

    • 如果使用 OpenGL,可以通过 QOpenGLFramebufferObject转换为 QImage。

  • 将渲染结果作为纹理上传到 GPU。

  • 用于后续的图像处理或分析。

3.3.4、示例代码

#include <QGuiApplication>
#include <QOffscreenSurface>
#include <QPainter>
#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <QOpenGLFramebufferObject>

int main(int argc, char *argv[])
{
    QGuiApplication a(argc, argv);

    // 创建并配置离屏表面
    QOffscreenSurface surface;
    QSurfaceFormat format;
    format.setRenderableType(QSurfaceFormat::OpenGL); // 使用 OpenGL
    surface.setFormat(format);
    surface.create();
    if (!surface.isValid()) {
        qFatal("Failed to create QOffscreenSurface");
    }

    // 定义图像大小
    QSize imageSize(800, 600);

    // 使用 QPainter 进行光栅化渲染
    QImage image(imageSize, QImage::Format_ARGB32);
    QPainter painter(&image);
    painter.fillRect(0, 0, image.width(), image.height(), Qt::blue);
    painter.setPen(Qt::white);
    painter.setFont(QFont("Arial", 24));
    painter.drawText(10, 50, "Offscreen Rendering");
    image.save("output.png");

    // 使用 OpenGL 进行渲染
    QOpenGLContext context;
    context.setFormat(surface.format());
    if (!context.create()) {
        qFatal("Failed to create QOpenGLContext");
    }
    context.makeCurrent(&surface);

    // 初始化 OpenGL 函数
    QOpenGLFunctions *gl = context.functions();

    // 创建帧缓冲区对象 (FBO)
    QOpenGLFramebufferObject fbo(imageSize);
    fbo.bind();

    // 设置 OpenGL 视口
    gl->glViewport(0, 0, imageSize.width(), imageSize.height());
    gl->glClearColor(0.0f, 0.0f, 1.0f, 1.0f); // 设置清屏颜色为蓝色
    gl->glClear(GL_COLOR_BUFFER_BIT);

    // 读取 FBO 的像素数据
    QImage imageGL = fbo.toImage(); // 直接从 FBO 获取图像
    fbo.release(); // 释放 FBO
    context.doneCurrent();

    // 翻转图像(OpenGL 坐标系与 Qt 不同)
    imageGL = imageGL.mirrored();
    imageGL.save("opengl_output.png");

    return a.exec();
}

//========================
//console 
//========================
//output.png:
//大小:800x600 像素。

//内容:蓝色背景,白色文本 "Offscreen Rendering"(Arial 字体,24 号,位置 (10, 50))。

//opengl_output.png:
//大小:800x600 像素。

//内容:纯蓝色填充(由 glClearColor(0.0f, 0.0f, 1.0f, 1.0f) 决定)。


4、高级主题

4.1、自定义窗口框架 (基于 QWindow)

自定义窗口框架允许开发者创建完全个性化的窗口外观和行为,通常用于实现独特的用户界面设计,例如无边框窗口或自定义标题栏。

4.1.1、使用 Qt::FramelessWindowHint 创建无边框窗口

Qt::FramelessWindowHint 是一个窗口标志,用于移除操作系统的默认窗口边框和标题栏,适合创建自定义窗口样式。

实现步骤:

  • 创建一个 QWindow 实例或继承 QWindow 的子类。

  • 设置窗口标志 Qt::FramelessWindowHint。

  • 可选:结合其他标志(如 Qt::Window)以确保窗口行为符合需求。

  • 注:无边框窗口不会自动包含关闭、最小化、最大化按钮,需手动实现。

4.1.2、手动实现标题栏拖动、缩放和关闭功能

  • 标题栏拖动:通过捕获鼠标按下、移动和释放事件,实现窗口拖动。

  • 窗口缩放:实现窗口缩放需要检测鼠标是否位于窗口边缘,并根据鼠标移动调整窗口大小。

  • 关闭功能:实现关闭按钮通常结合自定义 UI(如 QPushButton)或直接处理鼠标点击事件。

4.1.3、鼠标事件和几何管理的结合

自定义窗口需要精确处理鼠标事件与窗口几何形状的交互,以实现流畅的用户体验。

关键点:

  • 鼠标事件:使用 mousePressEvent、mouseMoveEvent、mouseReleaseEvent 等捕获用户输入。

  • 几何管理:通过 setGeometry、setPosition 等方法动态调整窗口位置和大小。

  • 区域判断:结合 QRect 和 QPoint 判断鼠标是否在标题栏、边缘或按钮区域。

  • 事件过滤:对于复杂 UI,可使用 eventFilter 拦截子控件事件。

4.1.4、示例代码

#include <QWindow>
#include <QApplication>
#include <QMouseEvent>


class CustomWindow : public QWindow {
public:
    CustomWindow() {
        setFlags(Qt::FramelessWindowHint | Qt::Window); // 无边框窗口
        setMinimumSize(QSize(400, 300)); // 设置最小尺寸
        setTitle("Custom Window");
    }

protected:

    void mousePressEvent(QMouseEvent *event) override {
        if (event->button() == Qt::LeftButton) {

            //在鼠标按下时,判断鼠标位置是否在可缩放区域。
            m_resizeMode = getResizeMode(event->pos());
            m_dragPosition = event->globalPos();
            //记录鼠标按下时的全局位置和窗口位置。
            if(m_resizeMode ==ResizeMode::None){
                m_dragging = true;
                m_dragPosition = event->globalPos() - position();
            }

            // 假设关闭按钮区域在右上角 30x30 像素
            QRect closeButtonRect(width() - 30, 0, 30, 30);
            if (closeButtonRect.contains(event->pos())) {
                close();
            }
        }
    }

    void mouseMoveEvent(QMouseEvent *event) override {

        //在鼠标移动时,动态调整窗口的几何形状。
        if (m_resizeMode != None && (event->buttons() & Qt::LeftButton)) {
            QRect geo = geometry();
            QPoint delta = event->globalPos() - m_dragPosition;
            if (m_resizeMode & Left) geo.setLeft(geo.left() + delta.x());
            if (m_resizeMode & Right) geo.setRight(geo.right() + delta.x());
            if (m_resizeMode & Top) geo.setTop(geo.top() + delta.y());
            if (m_resizeMode & Bottom) geo.setBottom(geo.bottom() + delta.y());
            setGeometry(geo);
            m_dragPosition = event->globalPos();
            //在鼠标移动时,计算新位置并更新窗口位置。
        }else if (m_dragging && (event->buttons() & Qt::LeftButton)) {
            setPosition(event->globalPos() - m_dragPosition);
        }
    }


    void mouseReleaseEvent(QMouseEvent *event) override {
        if (event->button() == Qt::LeftButton) {
            m_dragging = false;
        }
    }
private:
    enum ResizeMode { None, Left, Right, Top, Bottom, TopLeft, TopRight, BottomLeft, BottomRight };

    //定义窗口边缘区域(例如,边界 5 像素)。
    ResizeMode getResizeMode(const QPoint &pos) {
        const int margin = 5;
        bool left = pos.x() < margin;
        bool right = pos.x() > width() - margin;
        bool top = pos.y() < margin;
        bool bottom = pos.y() > height() - margin;

        if (left && top) return TopLeft;
        if (right && top) return TopRight;
        if (left && bottom) return BottomLeft;
        if (right && bottom) return BottomRight;
        if (left) return Left;
        if (right) return Right;
        if (top) return Top;
        if (bottom) return Bottom;
        return None;
    }
private:
    //使用成员变量跟踪拖动状态。
    bool m_dragging = false;
    QPoint m_dragPosition;
    ResizeMode m_resizeMode =ResizeMode::None;
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    CustomWindow window;
    window.show();
    return app.exec();
}

4.2、透明和半透明窗口 (基于 QWindow)

透明和半透明窗口常用于创建现代化的 UI 效果,例如浮动面板、提示窗口或自定义对话框。

4.2.1、设置窗口透明度 (setOpacity())

用于设置窗口的整体透明度,取值范围为 0.0(完全透明)到 1.0(完全不透明)。实现步骤:

  • 创建 QWindow 实例。

  • 调用 setOpacity(double) 设置透明度。

  • 可动态调整透明度以实现淡入淡出效果。

  • 注:透明度对整个窗口生效,包括内容区域。频繁更改透明度可能导致渲染开销。

4.2.2、使用 QSurfaceFormat 配置

  • 设置 QSurfaceFormat 的 alphaBufferSize 为 8,启用 alpha 通道。

  • 使用 QPainter 绘制自定义内容,背景保持透明。

  • 使用 setMask() 定义窗口形状。

4.2.3、处理透明区域的鼠标事件

透明区域的鼠标事件处理是实现交互性窗口的关键,例如在不规则形状窗口中只响应特定区域的点击。实现步骤:

  • 使用 setMask() 定义窗口的可见区域,鼠标事件仅在该区域触发。

  • 重写 mousePressEvent 等方法,检查鼠标位置是否在有效区域。

  • 可结合 QRegion 或自定义逻辑判断有效点击区域。

4.2.4、示例代码(windows)

#include <QWindow>
#include <QApplication>
#include <QPainter>
#include <QMouseEvent>
#include <QTimer>
#include <QDebug>
#include <QRegion>
#include <QSurfaceFormat>
#include <QBackingStore>

class TransparentWindow : public QWindow {
public:
    TransparentWindow() {
        // 设置无边框窗口和透明表面
        setFlags(Qt::FramelessWindowHint | Qt::Window);
        QSurfaceFormat format = this->format();
        format.setAlphaBufferSize(8); // 启用透明通道
        setFormat(format);
        setMinimumSize(QSize(400, 300));

        // 初始化后备存储
        m_backingStore = new QBackingStore(this);

        // 设置初始透明度
        setOpacity(0.5); // 初始透明度为50%

        // 定义窗口形状和鼠标事件的椭圆区域
        QRegion region(QRect(50, 50, 300, 200), QRegion::Ellipse);
        setMask(region);

        // 动态调整透明度(淡入淡出效果)
        QTimer *timer = new QTimer(this);
        connect(timer, &QTimer::timeout, this, [this]() {
            static double opacity = 0.5;
            opacity += 0.1;
            if (opacity > 1.0) opacity = 0.1;
            setOpacity(opacity);
        });
        timer->start(500); // 每500毫秒更新一次透明度
    }

protected:
    // 处理窗口暴露事件
    void exposeEvent(QExposeEvent *event) override {
        if (!isExposed()) return;

        // 调整后备存储大小以匹配窗口大小
        m_backingStore->resize(size());

        // 开始绘制
        QRect windowRect(0, 0, width(), height());
        m_backingStore->beginPaint(QRegion(windowRect));

        // 获取绘制设备
        QPaintDevice *device = m_backingStore->paintDevice();
        QPainter painter(device);
        painter.setRenderHint(QPainter::Antialiasing); // 启用抗锯齿

        // 用透明颜色清除背景
        painter.fillRect(windowRect, Qt::transparent);

        // 绘制椭圆内容
        painter.setBrush(Qt::blue); // 填充蓝色
        painter.drawEllipse(50, 50, 300, 200); // 椭圆区域

        // 结束绘制
        m_backingStore->endPaint();

        // 将后备存储刷新到窗口
        m_backingStore->flush(QRegion(windowRect));

        // 如果需要,安排更新以确保连续渲染
        requestUpdate();
    }

    // 处理窗口大小调整事件以更新后备存储
    void resizeEvent(QResizeEvent *event) override {
        m_backingStore->resize(size());
        QWindow::resizeEvent(event);
    }

    // 处理鼠标点击事件
    void mousePressEvent(QMouseEvent *event) override {
        QRect activeArea(50, 50, 300, 200); // 定义可点击区域
        if (activeArea.contains(event->pos())) {
            qDebug() << "点击了有效区域!";
        } else {
            qDebug() << "点击了透明区域!";
        }
    }

private:
    QBackingStore *m_backingStore; // 用于渲染的后备存储
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    TransparentWindow window;
    window.show();
    return app.exec();
}

二. 绘图和渲染

提供 2D 绘图功能,包括线条、形状、文本和变换。

  • QPainter: 2D 绘图引擎,支持绘制线条、形状、文本、图像。

  • QPaintDevice: 绘图设备基类(支持 QImage、QPixmap,不包括 QWidget)。

  • QPen: 线条样式(颜色、宽度、样式)。

  • QBrush: 填充样式(颜色、渐变、图案)。

  • QGradient: 渐变填充(包括 QLinearGradient、QRadialGradient、QConicalGradient)。

  • QPaintEngine: 底层绘图引擎抽象,支持不同渲染后端(如 Raster、OpenGL)。

  • QRegion: 2D 区域,用于裁剪和碰撞检测。

  • QPainterPath: 复杂路径绘制(如贝塞尔曲线)。

  • QTransform: 2D 变换(旋转、缩放、平移)。

  • QMatrix4x4, QVector2D, QVector3D, QVector4D: 高级变换和坐标(常用于 OpenGL)。

  • QTextItem: 低级文本渲染(不依赖控件)。

三. 图像处理

支持图像创建、操作和文件读写。

  • QImage: 像素级图像操作,适合图像处理。

  • QPixmap: 优化用于屏幕显示的图像。

  • QBitmap: 单色位图。

  • QPicture: 记录和重放绘图指令。

  • QImageReader, QImageWriter: 图像文件读写(支持 PNG、JPEG 等格式)。

  • QMovie: 动态图像播放(如 GIF)。

  • QImageIOHandler: 自定义图像格式处理。

  • QImageEncoderSettings, QImageDecoder (Qt 6): 图像编码/解码设置。

四. 字体和文本

提供字体管理和低级文本渲染功能。

  • QFont: 字体属性管理(大小、粗细、样式)。

  • QFontMetrics, QFontMetricsF: 字体度量,计算文本尺寸。

  • QFontDatabase: 系统字体资源访问。

  • QTextLayout, QTextOption: 高级文本布局和格式化。

  • QRawFont: 直接访问字体文件数据。

  • QTextFragment, QTextBlock: 低级文本结构(用于复杂文本渲染)。

  • QGlyphRun: 字形级文本渲染。

五. 事件和输入处理

处理 GUI 相关的用户输入和交互事件。

  • QMouseEvent: 鼠标点击、移动事件。

  • QHoverEvent: 鼠标悬停事件。

  • QWheelEvent: 鼠标滚轮事件。

  • QKeyEvent: 键盘输入事件。

  • QTouchEvent: 触摸输入事件。

  • QNativeGestureEvent: 平台特定手势(如 macOS 手势)。

  • QInputMethod, QInputMethodEvent: 输入法支持(虚拟键盘、语言切换)。

  • QDrag, QDropEvent: 拖放操作。

  • QClipboard: 剪贴板访问。

  • QTabletEvent: 数位板输入事件。

  • QEnterEvent (Qt 6): 鼠标进入/离开事件。

  • QExposeEvent: 窗口暴露事件。

  • QPlatformDrag: 平台特定的拖放实现。

六. OpenGL 和硬件加速

支持 OpenGL 和 Vulkan 渲染,适用于高性能图形。

  • QOpenGLContext: OpenGL 上下文管理。

  • QOpenGLFunctions, QOpenGLExtraFunctions: OpenGL API 封装。

  • QOpenGLFramebufferObject: 帧缓冲对象,用于离屏渲染。

  • QOpenGLShader, QOpenGLShaderProgram: 着色器支持。

  • QOpenGLTexture: 纹理管理。

  • QOpenGLBuffer: 顶点和索引缓冲区。

  • QOpenGLVertexArrayObject: 顶点数组对象。

  • QOpenGLTimerQuery, QOpenGLTimeMonitor: OpenGL 性能监控。

  • QAbstractOpenGLFunctions (Qt 6): 抽象化的 OpenGL 函数接口。

  • QVulkanInstance, QVulkanWindow (Qt 6): Vulkan 渲染支持。

七. 颜色和外观

管理颜色和外观设置。

  • QColor: 颜色表示(支持 RGB、HSV、CMYK)。

  • QPalette: 颜色方案管理(前景、背景等)。

  • QColorSpace (Qt 6): 颜色空间管理(支持 ICC 配置文件)。

  • QColormap: 颜色映射(主要用于旧平台)。

八. 图标和光标

支持图标和鼠标光标管理。

  • QIcon: 图标管理,支持多分辨率和状态。

  • QCursor: 鼠标光标样式和自定义形状。

  • QIconEngine: 自定义图标渲染引擎。

九. 平台和渲染后端

提供平台特定集成和渲染后端支持。

  • QPlatformIntegration: 平台特定的窗口系统集成(Windows、X11、Wayland 等)。

  • QRasterPaintEngine: 软件光栅化渲染引擎。

  • QPlatformSurface: 平台特定的渲染表面。

  • QPlatformTheme: 平台主题(如按钮样式、对话框风格)。

  • QPlatformGraphicsBuffer: 平台特定的图形缓冲区。

  • QPlatformSharedGraphicsCache: 共享图形缓存,加速渲染。

十. 国际化(GUI 相关)

支持 GUI 相关的字符编码和区域设置。

  • QTextCodec(部分):字符编码支持(仅限 GUI 文本显示)。

  • QLocale(部分):区域设置(仅限 GUI 格式,如日期、数字显示)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旭唐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值