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

QtGUI模块功能详细说明, 字体和文本渲染(四)

目录

一. 窗口和屏幕管理

二. 绘图和渲染

三. 图像处理

四. 字体和文本

1、核心概念

1.1、字体 (Font)

1.2、字形 (Glyph)

1.3、字符 (Character)

1.4、文本布局 (Text Layout)

1.5、文本渲染 (Text Rendering)

1.6、度量 (Metrics)

2、字体管理

2.1、QFont:字体属性管理

2.2、QFontDatabase:系统字体资源访问

3、字体度量

3.1、基于 QFont 创建度量对象

3.2、字高 (Height)、行距 (Leading)、下行距 (Descent)、上行距 (Ascent)

3.3、X高度 (XHeight)、大写字母高度 (CapHeight)

3.4、字符宽度 (Width) 和文本字符串宽度计算

3.5、边界矩形 (Bounding Rect) 计算

3.6、字符或文本在给定宽度下是否适合

3.7、绘制文本时的偏移和位置信息

4、文本布局与格式化

4.1、QTextOption:高级文本布局选项

4.2、QTextLayout:执行文本布局

5、低级文本结构

5.1、QTextBlock:文本块处理 (用于复杂文本渲染)

5.2、QTextFragment:文本片段处理 (用于复杂文本渲染)

6、字形级文本渲染

6.1、QRawFont:直接访问字体文件数据

6.2、QGlyphRun:字形级文本渲染

6.3、示例代码

7、文本渲染与绘图

7.1、QPainter::drawText():简单文本绘制

7.2、QPainter::drawStaticText():优化绘制静态文本

7.3、QPainter::drawGlyphRun():绘制字形序列

7.5、基本用法:使用 QTextLayout::draw()

8、示例代码

8.1、绘制简单的文本标签

8.2、计算和显示文本的尺寸

8.3、加载和使用自定义字体

8.4、实现文本编辑器或查看器中的文本布局

五. 事件和输入处理

六. OpenGL 和硬件加速

七. 颜色和外观

八. 图标和光标

九. 平台和渲染后端

十. 国际化(GUI 相关)


一. 窗口和屏幕管理

提供跨平台窗口创建、管理以及屏幕信息访问功能。

请跳转章节,此处不再重复:QtGUI模块功能详细说明,窗口和屏幕管理(一)

二. 绘图和渲染

2D 绘图是指在二维平面(通常以像素为单位)上绘制图形、图像和文本的过程。

 请跳转章节,此处不再重复:QtGUI模块功能详细说明,图形绘制与渲染(二)

三. 图像处理

Qt 的图像处理功能核心类包括 QImage、QPixmap、QBitmap 和 QPainter。

 请跳转章节,此处不再重复:QtGUI模块功能详细说明,图像处理(三)

四. 字体和文本

1、核心概念

1.1、字体 (Font)

字体是一组定义字形外观的集合,通常包括字体的家族(如 Arial、Times New Roman)、样式(如粗体、斜体)和大小。字体文件(如 TrueType、OpenType)包含字形数据和排版规则。

QFont 类用于设置字体属性(如家族、大小、粗细)。

QFont font("Arial", 12, QFont::Bold);

1.2、字形 (Glyph)

字形是字符的可视化表示,是字体文件中定义的具体图形形状。一个字符可能对应多个字形(例如,粗体和斜体的“a”字形不同)。

QGlyphRun 类用于管理字形及其位置,底层通过字体引擎(如 FreeType 或平台原生引擎)将字符映射到字形。

1.3、字符 (Character)

字符是文本的基本单位,通常以 Unicode 码点表示。Unicode 提供了全球字符的统一编码,支持多语言文本。

QString 类基于 Unicode 存储和操作字符。

QString text = QString::fromUtf8("你好,世界!");

1.4、文本布局 (Text Layout)

文本布局是指确定字形在屏幕上的位置和顺序,包括对齐、换行、行距和复杂脚本的处理(如右到左或双向文本)。

  • 支持多行文本和自动换行。

  • 处理复杂脚本(如阿拉伯文、泰文)的字形连接和方向。

  • 提供对齐(左对齐、居中、右对齐)和间距调整。

QTextLayout 类负责文本的逻辑布局,结合 QFont QTextOption 处理排版规则。

QTextLayout layout;
layout.setText("Hello, World!");
layout.setFont(QFont("Arial", 12));
layout.beginLayout();
QTextLine line = layout.createLine();
layout.endLayout();

1.5、文本渲染 (Text Rendering)

文本渲染是将字形绘制到输出设备(如屏幕、打印机)的过程,通常涉及光栅化(rasterization)和抗锯齿技术。

QPainter 类负责将文本绘制到 QPaintDevice 上。

QPainter painter(this);
painter.setFont(QFont("Arial", 12));
painter.drawText(10, 50, "Hello, World!");

1.6、度量 (Metrics)

字体度量是描述字体尺寸和布局的信息,包括字高、行距、基线位置等。

  • Ascent:字形顶部到基线的距离。

  • Descent:字形底部到基线的距离。

  • Leading:行间距,影响多行文本的垂直间距。

  • Bounding Box:字形的边界框,用于碰撞检测和布局计算。

QFontMetrics 类提供度量信息。

QFontMetrics metrics(QFont("Arial", 12));
int height = metrics.height(); // 获取字体高度
int width = metrics.horizontalAdvance("Hello"); // 获取文本宽度

2、字体管理

字体管理是 Qt 中文本渲染的核心环节,涉及字体的创建、配置和系统字体资源的访问。Qt 提供了 QFont 类用于管理字体属性,QFontDatabase 类用于访问和操作系统中的字体资源。

2.1、QFont:字体属性管理

QFont 是 Qt 中用于定义和操作字体属性的核心类,允许开发者设置字体家族、大小、样式等属性,并控制渲染效果。

2.1.1、创建和初始化 QFont 对象

QFont 对象可以通过构造函数或设置函数初始化,支持多种构造方式:

// 默认构造函数,创建系统默认字体
QFont font;// 指定字体家族和字号
QFont font("Arial", 12);// 指定字体家族、字号、字重和斜体
QFont font("Times New Roman", 14, QFont::Bold, true);
  • 初始化后修改:

QFont font;
font.setFamily("Helvetica");
font.setPointSize(16);

2.1.2、设置字体家族 (Font Family)

字体家族指定字体名称(如 Arial、Times New Roman)。Qt 会尝试加载指定家族,若不可用,则使用系统回退字体。

  • 字体家族名称大小写敏感。

  • 可通过 QFontDatabase 查询可用字体家族(见下文)。

  • 使用 setFamily() 设置后,Qt 会根据平台字体引擎查找匹配字体。

font.setFamily("Arial");

2.1.3、设置字号 (Point Size / Pixel Size)

字号定义字体大小,Qt 支持两种单位:使用 setPointSize() 确保跨设备缩放一致;使用 setPixelSize() 适合固定像素场景(如嵌入式设备)。

  • Point Size:基于印刷点的逻辑大小(1 点 ≈ 1/72 英寸),适合跨平台一致性。

font.setPointSize(12); // 设置 12 点
  • Pixel Size:基于屏幕像素的物理大小,适合精确控制

font.setPixelSize(16); // 设置 16 像素

2.1.4、设置字重 (Weight)

字重控制字体的粗细,Qt 使用 QFont::Weight 枚举定义:

  • QFont::Light(较细)

  • QFont::Normal(标准)

  • QFont::Bold(粗体)

  • QFont::Black(极粗)

    font.setWeight(QFont::Bold); // 设置粗体
    • 数值设置:可通过整数(0-99)精确控制字重,兼容 OpenType 字体。

    font.setWeight(75); // 接近 Bold 的字重

    2.1.5、设置字体样式 (Style: Normal, Italic, Oblique)

    字体样式控制字形倾斜效果:

    • QFont::StyleNormal:正常样式。

    • QFont::StyleItalic:斜体(基于字体设计的倾斜字形)。

    • QFont::StyleOblique:倾斜(通过算法倾斜正常字形)。

    font.setStyle(QFont::StyleItalic); // 设置斜体

    2.1.6、设置下划线、删除线

    QFont 支持文本装饰效果:常用于强调文本或标记(如超链接、已删除内容)。

    font.setUnderline(true); // 添加下划线
    font.setStrikeOut(true); // 添加删除线
    font.setOverline(true);  // 添加上划线

    2.1.7、设置大写、小写、小型大写字母等属性

    QFont 支持控制字母大小写效果:

    • 全大写:将小写字母渲染为大写。

    font.setCapitalization(QFont::AllUppercase);
    • 全小写:

    font.setCapitalization(QFont::AllLowercase);
    • 小型大写:将小写字母渲染为小型大写字母(常用于标题)。

    font.setCapitalization(QFont::SmallCaps);

    2.1.8、设置字体拉伸 (Stretch)

    字体拉伸控制字形的宽度(压缩或拉伸),通过 QFont::Stretch 枚举或百分比值设置:

    • UltraCondensed(50%)

    • Normal(100%)

    • UltraExpanded(200%)

    font.setStretch(QFont::Condensed); // 设置压缩字体
    font.setStretch(120); // 设置 120% 宽度

    2.1.9、设置字体 hinting 和抗锯齿 (Antialiasing)

    抗锯齿可能增加渲染开销,适合高分辨率显示;Hinting 适合嵌入式设备或低分辨率屏幕。

    • Hinting:优化字体在低分辨率显示器上的清晰度。

    font.setHintingPreference(QFont::PreferFullHinting); // 完全 hinting
    font.setHintingPreference(QFont::PreferNoHinting);  // 无 hinting
    • 抗锯齿:平滑字体边缘,提升渲染质量。

    font.setStyleStrategy(QFont::PreferAntialias); // 启用抗锯齿
    font.setStyleStrategy(QFont::NoAntialias);     // 禁用抗锯齿

    2.1.10、字体比较和赋值

    • 比较:QFont 支持通过 == 和 != 比较字体属性。

    QFont font1("Arial", 12);
    QFont font2("Arial", 12);
    bool equal = (font1 == font2); // true
    • 赋值:直接赋值或使用 QFont 的拷贝构造函数。

    QFont font1("Arial", 12);
    QFont font2 = font1; // 深拷贝

    2.2、QFontDatabase:系统字体资源访问

    QFontDatabase 类提供对系统字体资源的访问,允许开发者查询可用字体、添加私有字体以及管理字体别名。以下是其详细功能。

    2.2.1、访问系统中可用的字体家族和样式

    QFontDatabase 可查询系统中安装的字体家族和样式:

    QFontDatabase database;
    QStringList families = database.families(); // 获取所有字体家族
    for (const QString &family : families) {qDebug() << "Font Family:" << family;
    }
    • 筛选字体:可指定字体类型。

    QStringList monoFamilies = database.families(QFontDatabase::Latin);

    2.2.2、根据字体家族和样式查找字体 ID

    QFontDatabase 提供字体属性的详细查询:

    QStringList styles = database.styles("Arial"); // 获取 Arial 的可用样式(如 Regular、Bold)
    for (const QString &style : styles) {qDebug() << "Style:" << style;
    }
    • 字体 ID:部分平台支持通过字体 ID 直接访问字体(较少使用)。

    2.2.3、添加和移除应用程序私有字体

    开发者可以加载外部字体文件(如 TTF、OTF)到应用程序中:

    int fontId = database.addApplicationFont("path/to/customfont.ttf");
    if (fontId != -1) {QStringList loadedFamilies = database.applicationFontFamilies(fontId);qDebug() << "Loaded Fonts:" << loadedFamilies;
    }
    • 移除字体:

    database.removeApplicationFont(fontId);
    • 注意:

      • 加载的字体仅在应用程序生命周期内有效。

      • 支持批量加载多个字体文件。

    2.2.4、查询字体属性

    QFontDatabase 可检查字体是否支持特定属性:

    bool hasBold = database.bold("Arial", "Regular"); // 检查 Arial Regular 是否支持粗体
    bool hasItalic = database.italic("Arial", "Regular"); // 检查是否支持斜体

    2.2.5、示例代码

    #include <QApplication>
    #include <QFontDatabase>
    #include <QLabel>
    #include <QDebug>int main(int argc, char *argv[]) {QApplication app(argc, argv);// 1. 创建和配置 QFontQFont font("Arial", 14);font.setWeight(QFont::Bold);font.setStyle(QFont::StyleItalic);font.setUnderline(true);font.setStyleStrategy(QFont::PreferAntialias);// 2. 使用 QFontDatabase 查询字体QFontDatabase database;QStringList families = database.families();qDebug() << "Available Font Families:" << families;// 3. 加载私有字体int fontId = database.addApplicationFont("path/to/customfont.ttf");if (fontId != -1) {QStringList loadedFonts = database.applicationFontFamilies(fontId);font.setFamily(loadedFonts.first()); // 使用加载的字体}// 4. 显示文本QLabel label("Hello, Qt Fonts!");label.setFont(font);label.show();return app.exec();
    }

    3、字体度量

    QFontMetrics 和 QFontMetricsF 是 Qt 框架中用于处理字体度量和文本尺寸计算的类,基于 QFont 对象创建。它们提供了一系列方法来获取字体和文本的几何信息,帮助开发者精确控制文本的绘制、布局和适配。

    3.1、基于 QFont 创建度量对象

    用于查询字体属性(如高度、宽度等)以及计算文本的尺寸和布局。

    • QFontMetrics:构造时传入 QFont 对象

      QFont font("Arial", 12);
      QFontMetrics metrics(font);
    • QFontMetricsF:同样基于 QFont,但提供浮点精度计算:

      QFontMetricsF metricsF(font);

    注意事项:

    • 度量对象与 QFont 的设置(如字体、字号、粗体等)直接相关,字体变化需要重新创建度量对象。

    • QFontMetrics 返回整数值(像素单位),适合大多数场景;

    • QFontMetricsF 返回浮点值,适合高精度需求(如打印或缩放)。

    3.2、字高 (Height)、行距 (Leading)、下行距 (Descent)、上行距 (Ascent)

    这些是字体度量的核心属性,用于描述字体在垂直方向的几何特性:

    3.2.1、字高 (Height):

    字体字符的总高度,包括上行距、下行距和可能的行间距。

    • 获取方法:

      int height = metrics.height(); // QFontMetrics
      qreal heightF = metricsF.height(); // QFontMetricsF

    3.2.2、行距 (Leading):

    行与行之间的额外间距,通常用于调整文本的视觉松紧度。

    • 获取方法:

      int leading = metrics.leading();
      qreal leadingF = metricsF.leading();
    • 注意:某些字体可能没有行距(leading 为 0)。

    3.2.3、下行距 (Descent):

    基线以下的部分高度,例如字母 "g"、"p" 的下垂部分。

    • 获取方法:

      int descent = metrics.descent();
      qreal descentF = metricsF.descent();
    • 用途:计算文本的底部边界,确保下垂字符不被裁剪。

    3.2.4、上行距 (Ascent):

    基线以上的部分高度,例如字母 "h"、"l" 的上部。

    • 获取方法:

      int ascent = metrics.ascent();
      qreal ascentF = metricsF.ascent();
    • 用途:计算文本的顶部边界,确定绘制起点。

    3.2.5、关系:

    • 通常,Height ≈ Ascent + Descent + Leading,但具体值取决于字体设计。

    • 基线(Baseline)是文本绘制的参考线,位于 Ascent 和 Descent 之间。

    3.3、X高度 (XHeight)、大写字母高度 (CapHeight)

    3.3.1、X高度 (XHeight):

    小写字母 "x" 的高度,代表小写字母的主体高度(不包括上行或下行部分)。

    • 获取方法:

      int xHeight = metrics.xHeight(); // QFontMetrics
      qreal xHeightF = metricsF.xHeight(); // QFontMetricsF
    • 用途:用于评估字体的小写字母视觉大小,常用于 UI 设计中的文本对齐。

    3.3.2、大写字母高度 (CapHeight):

    大写字母(如 "H"、"A")的高度,通常略小于 Ascent。

    • 获取方法:

      int capHeight = metrics.capHeight();
      qreal capHeightF = metricsF.capHeight();
    • 用途:用于精确计算大写文本的垂直空间需求。

    注意:并非所有字体都提供 XHeight 和 CapHeight 的精确值,某些字体可能返回近似值。

    3.4、字符宽度 (Width) 和文本字符串宽度计算

    3.4.1、字符宽度 (Width):

    计算单个字符的水平宽度。

    • 获取方法:

      int charWidth = metrics.width('A'); // QFontMetrics
      qreal charWidthF = metricsF.width('A'); // QFontMetricsF
    • 注意:不同字符宽度可能不同(例如,"i" 比 "W" 窄),取决于字体是否为等宽字体。

    3.4.2、文本字符串宽度:

    计算整个字符串的水平宽度,考虑字符间距和字体特性。

    • 获取方法:

      int textWidth = metrics.width("Hello, World!");
      qreal textWidthF = metricsF.width("Hello, World!");
    • 用途:用于确定文本是否适合特定区域,或计算文本对齐位置。

    3.4.3、高级方法:

    horizontalAdvance(QFontMetrics 和 QFontMetricsF):替代 width,更精确地表示字符或字符串的水平前进距离(包括字距调整)。

    int advance = metrics.horizontalAdvance("Hello");

    3.5、边界矩形 (Bounding Rect) 计算

    计算文本的边界矩形(QRect 或 QRectF),表示文本的最小包围框。

    • 获取方法:

      QRect rect = metrics.boundingRect("Hello, World!");
      QRectF rectF = metricsF.boundingRect("Hello, World!");
    • 用途:

      • 确定文本绘制时的精确位置和大小。

      • 考虑了字符的实际形状(例如,斜体字体的边界可能超出宽度计算)。

    • 重载方法:支持指定绘制区域、文本对齐方式和换行规则:

      QRect rect = metrics.boundingRect(x, y, width, height, Qt::AlignCenter, "Hello, World!");

    3.6、字符或文本在给定宽度下是否适合

    判断文本是否能在指定宽度内完整显示。

    • 在 UI 中处理长文本的显示(如标签、按钮)。

    • 动态调整文本以适应有限空间。

    3.6.1、获取方法:

    • QFontMetrics::elidedText:在文本过长时添加省略号(...)并截断。

      QString elided = metrics.elidedText("Very long text", Qt::ElideRight, 100);
      // 返回 "Very long..."
    • QFontMetrics::tightBoundingRect:计算紧密边界矩形,判断是否超出宽度。

    3.7、绘制文本时的偏移和位置信息

    3.7.1、绘制文本:

    • 使用 QPainter 绘制文本时,需根据度量信息计算绘制位置。

    • 基线位置通常由 Ascent 和 Descent 确定。

    QPainter painter;
    painter.setFont(font);
    int y = baselineY + metrics.ascent(); // 确保文本顶部对齐
    painter.drawText(x, y, "Hello, World!");

    3.7.2、偏移计算:

    • 水平对齐:使用 width 或 horizontalAdvance 调整文本的起始 x 坐标。

    • 垂直对齐:使用 Ascent、Descent 和 Height 确定 y 坐标。

    • 对于多行文本,需考虑 Leading 和 Height 来计算行间距。

    • 示例:

      int lineSpacing = metrics.leading() + metrics.height();
      int y = startY;
      for (const QString& line : lines) {painter.drawText(x, y + metrics.ascent(), line);y += lineSpacing;
      }

    4、文本布局与格式化

    QTextOption 和 QTextLayout 是 Qt 框架中用于高级文本布局和格式化的核心类。它们提供了强大的功能,用于控制文本的对齐、换行、方向以及复杂布局的计算和渲染。

    4.1、QTextOption:高级文本布局选项

    QTextOption 类用于定义文本布局的行为和格式化规则,通常与 QTextLayout 或 QPainter 一起使用。它允许开发者灵活控制文本的视觉表现和布局方式。

    4.1.1、文本对齐方式 (Alignment)

    控制文本在水平和垂直方向上的对齐方式。

    • 用于单行或多行文本的布局。

    • 在绘制文本时,通过 QPainter::drawText 或 QTextLayout 应用对齐规则。

    支持的对齐选项:

    • 水平对齐:

      • Qt::AlignJustify:两端对齐(常用于段落)。

      • Qt::AlignCenter:居中。

      • Qt::AlignRight:右对齐。

      • Qt::AlignLeft:左对齐(默认)。

    • 垂直对齐:

      • Qt::AlignTop:顶部对齐。

      • Qt::AlignBottom:底部对齐。

      • Qt::AlignVCenter:垂直居中。

    QTextOption option;
    option.setAlignment(Qt::AlignCenter | Qt::AlignVCenter);

    4.1.2、文本换行模式 (Word Wrap Mode)

    控制文本在指定宽度内的换行行为。

    • 控制多行文本在给定宽度内的自然换行。

    • 常用于文本编辑器、标签或段落布局。

    支持的换行模式(QTextOption::WrapMode):

    • QTextOption::NoWrap:不换行,文本保持单行。

    • QTextOption::WordWrap:在单词边界换行(默认)。

    • QTextOption::ManualWrap:仅在显式换行符(如 \n)处换行。

    • QTextOption::WrapAnywhere:在任意字符处换行(适合紧凑布局)。

    • QTextOption::WrapAtWordBoundaryOrAnywhere:优先在单词边界换行,若无法满足则在任意位置换行。

    QTextOption option;
    option.setWrapMode(QTextOption::WordWrap);

    4.1.3、文本方向 (Direction: Left-to-Right, Right-to-Left)

    指定文本的书写方向,特别适用于多语言支持。

    • 处理双向文本(BiDi),例如混合英语和阿拉伯语的文本。

    • 自动调整文本对齐和光标移动行为。

    • 支持的方向:

      • Qt::LeftToRight:从左到右(默认,适合英语、汉语等)。

      • Qt::RightToLeft:从右到左(适合阿拉伯语、希伯来语等)。

    QTextOption option;
    option.setTextDirection(Qt::RightToLeft);

    注意:

    • 文本方向会影响字符顺序和对齐方式。

    • Qt 的文本引擎会根据 Unicode BiDi 算法自动处理复杂方向。

    4.1.4、制表位 (Tab Stops)

    控制制表符(\t)的间距,用于对齐文本。

    • 实现表格式文本对齐。

    • 在代码编辑器或格式化文档中对齐内容。

    • 使用 setTabStopDistance 设置制表位间距(以像素为单位)。

      QTextOption option;
      option.setTabStopDistance(80.0); // 每 80 像素一个制表位
    • 高级用法:支持自定义制表位列表(setTabArray 或 setTabs)。

      QList<QTextOption::Tab> tabs;
      QTextOption::Tab tab;
      tab.position = 100.0;
      tab.type = QTextOption::LeftTab;
      tabs.append(tab);
      option.setTabs(tabs);

    4.1.5、文本标记 (Flags: 例如:IncludeTrailingSpaces)

    通过标志位控制文本处理的额外行为。

    • 增强文本布局的灵活性和调试能力。

    • 适用于文本编辑器或需要精确控制的场景。

    常用标志(QTextOption::Flag):

    • QTextOption::IncludeTrailingSpaces:在宽度计算时包含末尾空格。

    • QTextOption::ShowTabsAndSpaces:可视化显示制表符和空格(用于调试或编辑器)。

    • QTextOption::ShowLineAndParagraphSeparators:显示换行符和段落分隔符。

    • QTextOption::SuppressColors:忽略文本中的颜色标记。

      QTextOption option;
      option.setFlags(QTextOption::IncludeTrailingSpaces | QTextOption::ShowTabsAndSpaces);

    4.2、QTextLayout:执行文本布局

    QTextLayout 是 Qt 中用于执行复杂文本布局的类,负责将文本字符串分解为行、计算字形位置,并支持高级排版需求(如双向文本、嵌入对象等)。它通常与 QTextOption 配合使用。

    4.2.1、使用 QTextOption 和文本字符串创建 QTextLayout

    • 使用文本字符串和字体创建 QTextLayout:

      QString text = "Hello, World!\nThis is a test.";
      QFont font("Arial", 12);
      QTextLayout layout(text, font);
    • 可选:应用 QTextOption 设置布局规则:

      QTextOption option;
      option.setWrapMode(QTextOption::WordWrap);
      option.setTextDirection(Qt::LeftToRight);
      layout.setTextOption(option);

    4.2.2、执行布局计算 (beginLayout(), createLine(), endLayout())

    使用 beginLayout()、createLine() 和 endLayout() 完成文本的行分解和布局计算。

    • beginLayout():启动布局过程,清空之前的布局状态。

    • createLine():创建一行文本,返回 QTextLine 对象。

    • setLineWidth(width):设置行的最大宽度,触发换行计算。

    • setPosition(QPointF):设置行在画布中的位置。

    • endLayout():完成布局,锁定计算结果。

    QTextLayout layout(text, font);
    layout.beginLayout();
    qreal maxWidth = 200.0; // 最大宽度
    qreal y = 0.0;
    while (1) {QTextLine line = layout.createLine();if (!line.isValid())break;line.setLineWidth(maxWidth);line.setPosition(QPointF(0, y));y += line.height();
    }
    layout.endLayout();

    4.2.3、获取布局后的行 (Line) 信息

    • 使用 QTextLayout::lineCount() 获取行数。

    • 使用 QTextLayout::lineAt(index) 或 QTextLayout::lineForTextPosition(pos) 获取特定行。

    • QTextLine 提供以下信息:

      • textStart():行内文本的起始位置(在原始字符串中的索引)。

      • textLength():行内文本的长度。

      • width() 和 height():行的宽度和高度。

      • rect():行的边界矩形。

      • naturalTextWidth():行的自然宽度(未受最大宽度限制)。

      • x() 和 y():行在画布中的位置。

    for (int i = 0; i < layout.lineCount(); ++i) {QTextLine line = layout.lineAt(i);qDebug() << "Line" << i << ": width =" << line.width()<< ", height =" << line.height()<< ", text =" << text.mid(line.textStart(), line.textLength());
    }

    4.2.4、获取每个字形的位置和度量信息

    QTextLine::glyphRuns() 返回行的字形运行(QGlyphRun),包含每个字形的位置、字体和索引。

    QTextLine line = layout.lineAt(0);
    QList<QGlyphRun> glyphRuns = line.glyphRuns();
    for (const QGlyphRun& run : glyphRuns) {QVector<QPointF> positions = run.positions();for (const QPointF& pos : positions) {qDebug() << "Glyph position:" << pos;}
    }

    4.2.5、处理复杂的文本布局需求

    混合文本方向:QTextLayout 自动支持双向文本(BiDi),基于 Unicode BiDi 算法处理左到右和右到左文本的混合。

    QTextOption option;
    option.setTextDirection(Qt::RightToLeft);
    QString mixedText = "Hello, مرحبا!";
    QTextLayout layout(mixedText, font);
    layout.setTextOption(option);
    layout.beginLayout();
    QTextLine line = layout.createLine();
    line.setLineWidth(200);
    layout.endLayout();

    结果:文本将按正确的方向渲染(阿拉伯语从右到左,英语从左到右)。

    内嵌对象:支持嵌入图像、控件或其他非文本对象(通过 QTextLayout::setFormats 和 QTextCharFormat)。实现富文本布局,如在文本中嵌入图标或表格。

    QTextLayout layout;
    QTextCharFormat format;
    format.setObjectType(QTextFormat::ImageObject);
    format.setProperty(QTextFormat::ImageName, "image.png");
    layout.setFormats({{0, 1, format}});

    5、低级文本结构

    QTextBlock 和 QTextFragment 是 Qt 框架中用于处理富文本和复杂文档结构的低级组件。

    它们通常与 QTextDocument 一起使用,适用于需要精细控制文本内容和格式的场景,如文本编辑器、富文本显示或文档渲染。

    5.1、QTextBlock:文本块处理 (用于复杂文本渲染)

    QTextBlock 表示 QTextDocument 中的一个文本块,通常对应一个段落或一行文本(在逻辑上,而非视觉上的行)。它是富文本处理的核心结构,用于组织和管理文本内容、格式和元数据。

    5.1.1、在富文本或文档结构中表示一个文本块

    定义:

    • QTextBlock 是 QTextDocument 的基本逻辑单元,表示一段连续的文本,通常以换行符(\n)或文档结尾分隔。

    • 每个文本块可以包含多个 QTextFragment(具有不同格式的文本片段)。

    • 文本块可以附加格式信息(如段落对齐、缩进)和其他元数据(如用户数据)。

    特点:

    • 逻辑单元:表示文档中的段落或逻辑分组,而不是视觉上的行(视觉行由 QTextLayout 处理)。

    • 动态性:当文档内容更改时,QTextBlock 会自动更新。

    • 格式支持:支持段落级格式(如对齐、边距)和字符级格式(通过 QTextFragment)。

    QTextBlock 通常通过 QTextDocument 的迭代器或光标访问,而不是直接构造。

    QTextDocument doc("First paragraph\nSecond paragraph");
    QTextBlock block = doc.begin(); // 获取第一个文本块
    while (block.isValid()) {qDebug() << block.text(); // 输出块的纯文本内容block = block.next(); // 移动到下一个块
    }

    5.1.2、访问文本块的属性和内容

    文本内容:text()返回块的纯文本内容(不含格式)。

    QString text = block.text(); // 例如:"First paragraph"

    块格式:blockFormat()返回块的格式(QTextBlockFormat),包含段落级属性(如对齐、缩进、边距)。

    QTextBlockFormat format = block.blockFormat();
    qDebug() << format.alignment(); // 例如:Qt::AlignLeft

    字符格式:charFormat()返回块的默认字符格式(QTextCharFormat),用于未明确指定格式的文本。

    QTextCharFormat charFormat = block.charFormat();
    qDebug() << charFormat.font().family(); // 例如:"Arial"

    位置和导航:

    • position():返回块在文档中的起始字符位置。

    • length():返回块的字符长度(包括换行符)。

    • next() 和 previous():导航到下一个或上一个块。

    • isValid():检查块是否有效

    布局信息:layout():返回关联的 QTextLayout 对象,用于获取视觉行信息。

    QTextLayout* layout = block.layout();
    qDebug() << layout->lineCount(); // 视觉行数

    用户数据:

    • setUserData() 和 userData():附加自定义数据到块。

    • setUserState() 和 userState():附加整数状态(如折叠状态)。

      block.setUserState(1); // 例如,表示块被折叠

    5.1.3、与 QTextDocument 的集成

    • QTextDocument 是富文本的顶层容器,管理所有 QTextBlock。

    • 每个 QTextBlock 属于一个 QTextDocument,通过文档的迭代器或光标访问。

    • QTextDocument 提供块的全局上下文,例如字体、默认格式和文档结构。

    通过 QTextDocument::begin() 和 QTextDocument::end() 迭代块:

    QTextDocument doc("Paragraph 1\nParagraph 2");
    for (QTextBlock block = doc.begin(); block != doc.end(); block = block.next()) {qDebug() << block.text();
    }

    通过 QTextCursor 定位特定块:

    QTextCursor cursor(&doc);
    cursor.movePosition(QTextCursor::Start);
    QTextBlock block = cursor.block();
    qDebug() << block.text();

    使用 QTextCursor 修改块内容或格式:

    QTextCursor cursor(&doc);
    cursor.select(QTextCursor::BlockUnderCursor);
    QTextBlockFormat format;
    format.setAlignment(Qt::AlignCenter);
    cursor.mergeBlockFormat(format); // 设置段落居中

    5.2、QTextFragment:文本片段处理 (用于复杂文本渲染)

    QTextFragment 表示 QTextBlock 内具有相同字符格式(QTextCharFormat)的一段连续文本。它是文本渲染的最小单元,用于处理富文本中不同格式的子部分。

    5.2.1、表示具有相同格式的一段文本

    定义:

    • QTextFragment 是 QTextBlock 的子单元,表示一段具有统一格式的文本(例如,同一字体、颜色或加粗属性的文本)。

    • 片段由 QTextDocument 自动生成,当文本格式变化时(如插入加粗或变色文本),会创建新的片段。

    特点:

    • 格式统一:每个片段共享相同的 QTextCharFormat。

    • 动态生成:由文档的编辑操作(如插入、格式化)触发。

    • 不可直接创建:通过 QTextBlock 的迭代器访问。

    示例说明:富文本“Bold Italic Text”中,可能会生成三个片段:

    • “Bold”:加粗格式。

    • “Italic”:斜体格式。

    • “Text”:默认格式。

    5.2.2、访问文本片段的格式和内容

    文本内容:text()返回片段的纯文本内容。

    QString fragmentText = fragment.text(); // 例如:"Bold"

    字符格式:charFormat()返回片段的字符格式(QTextCharFormat)。

    QTextCharFormat format = fragment.charFormat();
    qDebug() << format.fontWeight(); // 例如:QFont::Bold

    位置和长度:

    • position():返回片段在文档中的起始字符位置。

    • length():返回片段的字符长度。

      qDebug() << fragment.position() << fragment.length();
    • 有效性:isValid():检查片段是否有效。

      if (fragment.isValid()) {qDebug() << fragment.text();
      }

    5.2.3、在 QTextBlock 中遍历 QTextFragment

    使用 QTextBlock::iterator 或 QTextBlock::begin() 和 QTextBlock::end() 迭代片段。

    QTextBlock block = doc.firstBlock();
    for (QTextBlock::iterator it = block.begin(); it != block.end(); ++it) {QTextFragment fragment = it.fragment();if (fragment.isValid()) {qDebug() << "Fragment text:" << fragment.text()<< "Format:" << fragment.charFormat().font().toString();}
    }

    通过 QTextCursor 定位并操作片段:

    QTextCursor cursor(&doc);
    cursor.movePosition(QTextCursor::Start);
    QTextFragment fragment = cursor.block().begin().fragment();
    qDebug() << fragment.text();

    5.2.4、示例代码

    #include <QTextDocument>
    #include <QTextCursor>
    #include <QTextCharFormat>
    #include <QDebug>int main() {// 创建富文本文档QTextDocument doc;QTextCursor cursor(&doc);// 插入格式化文本QTextCharFormat boldFormat;boldFormat.setFontWeight(QFont::Bold);cursor.insertText("Bold ", boldFormat);QTextCharFormat italicFormat;italicFormat.setFontItalic(true);cursor.insertText("Italic ", italicFormat);cursor.insertText("Normal\nSecond paragraph");// 遍历文档的块和片段for (QTextBlock block = doc.begin(); block != doc.end(); block = block.next()) {qDebug() << "Block text:" << block.text();qDebug() << "Block format alignment:" << block.blockFormat().alignment();// 遍历块内的片段for (QTextBlock::iterator it = block.begin(); it != block.end(); ++it) {QTextFragment fragment = it.fragment();if (fragment.isValid()) {QTextCharFormat format = fragment.charFormat();qDebug() << "Fragment text:" << fragment.text()<< "Bold:" << (format.fontWeight() == QFont::Bold)<< "Italic:" << format.fontItalic();}}}return 0;
    }

    6、字形级文本渲染

    字形级文本渲染是高级文本处理技术,允许开发者直接操作字体数据和字形布局,以实现精确的文本渲染效果。Qt 提供了 QRawFont 和 QGlyphRun 两个核心类来支持这一功能。

    6.1、QRawFont:直接访问字体文件数据

    QRawFont 是一个低级接口,用于从字体文件中提取和操作原始字体数据。它适合需要直接访问字体表、字形信息或进行自定义渲染的场景。

    • 加载字体文件:支持从 .ttf、.otf 等字体文件中加载原始数据,而无需通过系统字体管理器。

    • 访问字体表:可以提取字体文件中的元数据(如字符映射表、字形轮廓表等)。

    • 字形操作:支持根据字符或字形名称获取字形ID、轮廓以及相关度量信息。

    • 精确控制:适用于需要精细调整字形渲染的场景,如高级排版、字体设计工具或自定义文本效果。

    6.1.1、加载字体文件

    使用 QRawFont::fromFont(const QFont &font, QFontDatabase::WritingSystem writingSystem) 或 QRawFont(const QString &fileName, qreal pixelSize) 加载字体数据。

    QRawFont rawFont(QStringLiteral("path/to/font.ttf"), 16.0); // 加载 .ttf 文件,设置像素大小为 16
    if (rawFont.isValid()) {qDebug() << "Font loaded successfully!";
    }

    6.1.2、获取字体表

    • 使用 QRawFont::fontTable(const char *tagName) 获取字体文件中的特定表(如 "head"、"glyf"、"cmap" 等)。

    • 字体表包含字体元数据,如字符到字形的映射、字形轮廓等。

    6.1.3、获取字形ID

    方法 QRawFont::glyphIndexesForString(const QString &text) 将字符串转换为对应的字形ID列表。

    QString text = "Hello";
    QVector<quint32> glyphIndexes = rawFont.glyphIndexesForString(text);
    qDebug() << glyphIndexes; // 输出字形ID列表

    6.1.4、获取字形轮廓 (Glyph Outline)

    使用 QRawFont::pathForGlyph(quint32 glyphIndex) 获取指定字形的轮廓路径(QPainterPath)。

    字形轮廓可用于自定义渲染或生成矢量图形。

    QPainterPath path = rawFont.pathForGlyph(glyphIndexes[0]);
    QPainter painter(this);
    painter.drawPath(path); // 绘制字形轮廓

    6.1.5、获取字形度量和字距调整信息 (Kerning)

    • QRawFont::advancesForGlyphIndexes(const QVector<quint32> &glyphIndexes) 返回字形的推进宽度(advance width)。

    • QRawFont::supportsCharacter(QChar character) 检查字体是否支持特定字符。

    • 字距调整(Kerning)信息可通过字体表的 "kern" 表获取,用于优化字符间距。

    QVector<QPointF> advances = rawFont.advancesForGlyphIndexes(glyphIndexes);
    qDebug() << advances; // 输出每个字形的推进向量

    6.2、QGlyphRun:字形级文本渲染

    QGlyphRun 是一个表示字形序列的类,用于精确控制文本渲染中每个字形的位置和属性。它通常与 QPainter 结合使用,适合需要自定义字形布局的场景。

    6.2.1、设置字形数据

    • QGlyphRun::setRawFont(const QRawFont &rawFont):指定用于渲染的字体。

    • QGlyphRun::setGlyphIndexes(const QVector<quint32> &glyphIndexes):设置字形ID列表。

    • QGlyphRun::setPositions(const QVector<QPointF> &positions):设置每个字形的位置偏移。

    QGlyphRun glyphRun;
    glyphRun.setRawFont(rawFont);
    glyphRun.setGlyphIndexes(glyphIndexes);
    glyphRun.setPositions(positions); // 每个字形的位置

    6.2.2、渲染字形序列

    使用 QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun) 渲染字形序列。

    QPainter painter(this);
    painter.drawGlyphRun(QPointF(10, 50), glyphRun); // 在 (10, 50) 渲染字形序列

    6.2.3、获取字形数据

    • QGlyphRun::glyphIndexes():获取字形ID列表。

    • QGlyphRun::positions():获取每个字形的位置。

    • QGlyphRun::rawFont():获取关联的 QRawFont 对象。

    6.3、示例代码

    #include <QApplication>
    #include <QWidget>
    #include <QPainter>
    #include <QRawFont>
    #include <QGlyphRun>
    #include <QDebug>class Widget : public QWidget {
    protected:void paintEvent(QPaintEvent *) override {QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);// 加载字体文件QRawFont rawFont(QStringLiteral("path/to/font.ttf"), 32.0);if (!rawFont.isValid()) {qDebug() << "Failed to load font!";return;}// 获取字符串的字形IDQString text = "Hello";QVector<quint32> glyphIndexes = rawFont.glyphIndexesForString(text);// 计算字形位置QVector<QPointF> positions;qreal x = 10.0, y = 50.0;for (int i = 0; i < glyphIndexes.size(); ++i) {positions.append(QPointF(x, y));x += rawFont.advancesForGlyphIndexes({glyphIndexes[i]})[0].x();}// 创建 QGlyphRunQGlyphRun glyphRun;glyphRun.setRawFont(rawFont);glyphRun.setGlyphIndexes(glyphIndexes);glyphRun.setPositions(positions);// 渲染字形序列painter.setPen(Qt::black);painter.drawGlyphRun(QPointF(0, 0), glyphRun);}
    };int main(int argc, char *argv[]) {QApplication app(argc, argv);Widget widget;widget.resize(400, 200);widget.show();return app.exec();
    }
    

    7、文本渲染与绘图

    Qt 提供了多种工具和类(如 QPainter、QTextLayout、QFont 和 QFontMetrics)来实现灵活且高效的文本绘制。

    7.1、QPainter::drawText():简单文本绘制

    QPainter::drawText() 是绘制文本的最常用方法,适合快速渲染单行或多行文本。它支持多种重载形式,能够灵活指定绘制位置、矩形区域和对齐方式。

    • drawText(x, y, text):在指定坐标 (x, y) 处绘制文本。

    • drawText(rect, flags, text):在指定矩形 rect 内绘制文本,支持对齐选项(如 Qt::AlignCenter、Qt::AlignRight)。

      • Qt::TextWordWrap:自动换行。

      • Qt::AlignHCenter、Qt::AlignVCenter:水平和垂直居中。

    #include <QPainter>
    #include <QWidget>class MyWidget : public QWidget {
    protected:void paintEvent(QPaintEvent *) override {QPainter painter(this);painter.setFont(QFont("Arial", 12));painter.drawText(50, 50, "Hello, Qt!");QRect rect(50, 50, 200, 100);painter.drawText(rect, Qt::AlignCenter | Qt::TextWordWrap, "This is a long text that wraps within the rectangle.");}
    };

    7.2、QPainter::drawStaticText():优化绘制静态文本

    QPainter::drawStaticText() 专为静态文本优化,适合内容不经常变化的场景(如标签、标题)。它通过预计算文本布局来提高渲染效率。

    QStaticText staticText("Static Text Example");
    staticText.setTextFormat(Qt::PlainText); // 或 Qt::RichText
    painter.drawStaticText(QPointF(50, 50), staticText);

    7.3、QPainter::drawGlyphRun():绘制字形序列

    drawGlyphRun() 是一种低级绘制方法,用于直接绘制字形序列,适合需要精确控制文本渲染的场景(如自定义字体渲染或特殊效果)。

                QPainter painter(this);// 加载自定义字体QRawFont rawFont(QStringLiteral(":/fonts/custom.ttf"), 12, QFont::PreferDefaultHinting);if (!rawFont.isValid()) {return;}// 获取字形数据QString text = "Custom Glyphs";QVector<quint32> glyphIndexes = rawFont.glyphIndexesForString(text);QVector<QPointF> glyphPositions = rawFont.advancesForGlyphIndexes(glyphIndexes);if (glyphIndexes.isEmpty() || glyphPositions.isEmpty()) {return;}// 构造 QGlyphRunQGlyphRun glyphRun;glyphRun.setRawFont(rawFont);glyphRun.setGlyphIndexes(glyphIndexes);glyphRun.setPositions(glyphPositions);// 绘制字形序列painter.drawGlyphRun(QPointF(50, 50), glyphRun);

    7.4、结合 QFont 和 QFontMetrics 进行文本定位和绘制

    QFont 和 QFontMetrics 是文本渲染的重要辅助类,用于设置字体样式和计算文本尺寸。

    QFont:用于设置字体类型、大小、粗细等属性。

    QFont font("Arial", 14, QFont::Bold);
    painter.setFont(font);
    painter.drawText(50, 50, "Bold Arial Text");

    QFontMetrics:用于计算文本的尺寸和布局信息,如宽度、高度、行间距等。

    QFontMetrics metrics(font);
    int textWidth = metrics.horizontalAdvance("Hello, Qt!");
    int textHeight = metrics.height();
    QRect textRect(50, 50, textWidth, textHeight);
    painter.drawText(textRect, Qt::AlignLeft, "Hello, Qt!");

    精确定位:通过 QFontMetrics::boundingRect() 计算文本边界框,确保文本不被裁剪。

    QString text = "Dynamic Layout";
    QRect boundingRect = metrics.boundingRect(text);
    painter.drawText(boundingRect.translated(50, 50), Qt::AlignLeft, text);

    7.5、基本用法:使用 QTextLayout::draw()

    QTextLayout 可以将文本分解为行和字形运行,并支持复杂的排版需求。

    #include <QPainter>
    #include <QTextLayout>
    #include <QWidget>class MyWidget : public QWidget {
    protected:void paintEvent(QPaintEvent *) override {QPainter painter(this);QFont font("Arial", 12);painter.setFont(font);QString text = "This is a complex text with\nmultiple lines and <b>bold</b> formatting.";QTextLayout layout(text, font);layout.setTextOption(QTextOption(Qt::AlignLeft));// 设置文本格式(支持富文本)QTextCharFormat boldFormat;boldFormat.setFontWeight(QFont::Bold);layout.setFormats({{28, 4, boldFormat}}); // 应用粗体到 "bold"// 计算布局layout.beginLayout();QTextLine line = layout.createLine();line.setLineWidth(200); // 设置行宽,支持自动换行line.setPosition(QPointF(50, 50));layout.endLayout();// 绘制文本layout.draw(&painter, QPointF(0, 0));}
    };

    8、示例代码

    8.1、绘制简单的文本标签

    目标: 在窗口上绘制简单的文本标签。
    实现: 使用 QPainter 在自定义 QWidget 的 paintEvent 中绘制文本。

    #include <QPainter>
    #include <QWidget>
    #include <QApplication>class TextLabelWidget : public QWidget {
    protected:void paintEvent(QPaintEvent *) override {QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);QFont font("Arial", 16);painter.setFont(font);painter.setPen(Qt::blue);painter.drawText(100, 100, "Hello, Qt!");}
    };int main(int argc, char *argv[]) {QApplication app(argc, argv);TextLabelWidget widget;widget.resize(400, 300);widget.show();return app.exec();
    }
    

    8.2、计算和显示文本的尺寸

    目标: 计算文本的边界框并用矩形框显示。
    实现: 使用 QFontMetrics 计算文本尺寸,绘制文本和边界矩形。

    #include <QPainter>
    #include <QWidget>
    #include <QApplication>class TextSizeWidget : public QWidget {
    protected:void paintEvent(QPaintEvent *) override {QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);QFont font("Arial", 14);painter.setFont(font);QString text = "Sample Text";// 计算文本尺寸QFontMetrics metrics(font);QRect textRect = metrics.boundingRect(text);// 移动到窗口中心int x = (width() - textRect.width()) / 2;int y = (height() - textRect.height()) / 2;// 绘制文本painter.setPen(Qt::black);painter.drawText(x, y, text);// 绘制边界框painter.setPen(Qt::red);painter.drawRect(x, y - metrics.ascent(), textRect.width(), textRect.height());}
    };int main(int argc, char *argv[]) {QApplication app(argc, argv);TextSizeWidget widget;widget.resize(400, 300);widget.show();return app.exec();
    }
    

    8.3、加载和使用自定义字体

    目标: 加载外部 .ttf 字体并用于文本绘制,确保文件存在。
    实现: 使用 QFontDatabase 加载字体,应用到 QPainter。

    #include <QPainter>
    #include <QWidget>
    #include <QApplication>
    #include <QFontDatabase>class CustomFontWidget : public QWidget {
    protected:void paintEvent(QPaintEvent *) override {QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);// 加载自定义字体QFontDatabase fontDb;int fontId = fontDb.addApplicationFont("5.ttf");if (fontId == -1) {painter.drawText(100, 100, "Failed to load font!");return;}QString family = fontDb.families().first();QFont font(family, 16);painter.setFont(font);painter.setPen(Qt::black);painter.drawText(100, 100, "Custom Font Text");}
    };int main(int argc, char *argv[]) {QApplication app(argc, argv);CustomFontWidget widget;widget.resize(400, 300);widget.show();return app.exec();
    }
    

    8.4、实现文本编辑器或查看器中的文本布局

    目标: 创建支持多行文本、换行和对齐的编辑器。
    实现: 使用 QTextEdit 实现多行文本布局。

    #include <QPainter>
    #include <QWidget>
    #include <QApplication>
    #include <QFontDatabase>
    #include <QTextEdit>class TextEditorWidget : public QWidget {
    public:TextEditorWidget(QWidget *parent = nullptr) : QWidget(parent) {QTextEdit *editor = new QTextEdit(this);editor->setGeometry(10, 10, 380, 280);editor->setFont(QFont("Arial", 12));editor->setText("Editable text\nLine 2\nLine 3");editor->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);}
    };int main(int argc, char *argv[]) {QApplication app(argc, argv);TextEditorWidget widget;widget.resize(400, 300);widget.show();return app.exec();
    }
    

    五. 事件和输入处理

    处理 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 格式,如日期、数字显示)。

    相关文章:

    QtGUI模块功能详细说明, 字体和文本渲染(四)

    目录 一. 窗口和屏幕管理 二. 绘图和渲染 三. 图像处理 四. 字体和文本 1、核心概念 1.1、字体 (Font) 1.2、字形 (Glyph) 1.3、字符 (Character) 1.4、文本布局 (Text Layout) 1.5、文本渲染 (Text Rendering) 1.6、度量 (Metrics) 2、字体管理 2.1、QFont&#…...

    计算机学习路线与编程语言选择(信息差)

    ——授人以鱼不如授人以渔 面向岗位学习&#xff01;到招聘网站看看有哪些岗位&#xff0c;看一看岗位职责、要求 牛客网&#xff08;计算机实习工作最好的网站&#xff09; boss直聘 确定岗位后&#xff08;如前端、后端&#xff09;&#xff0c;岗位需要什么语言&#xf…...

    多环串级PID

    文章目录 为什么要多环程序主函数内环外环 双环PID调参内环Kp调法Ki调法 外环Kp 以一定速度到达指定位置封装 为什么要多环 单环只能单一控制速度或者位置&#xff0c;如果想要同时控制多个量如速度&#xff0c;位置&#xff0c;角度&#xff0c;就需要多个PID 速度环一般PI…...

    编写大模型Prompt提示词方法

    明确目标和任务 // 调用LLM进行分析const prompt 你是一名严格而友好的英语口语评分官&#xff0c;专业背景包括语音学&#xff08;phonetics&#xff09;、二语习得&#xff08;SLA&#xff09;和自动语音识别&#xff08;ASR&#xff09;。你的任务是&#xff1a; ① 比对参…...

    使用chrome浏览器截长图

    如何使用chrome浏览器截长图&#xff1a; 使用chrome截取完整网页图片 第一步、按F12&#xff0c;开发者模式的布局按下图布局 第二步、按ctrlshiftp组合键&#xff0c;搜索“截图” &#xff0c;然后自动截图保存在下载目录&#xff08;右上角&#xff09;了。...

    【MySQL】第二弹——MySQL表的增删改查(CURD))

    文章目录 &#x1f393;一. CRUD&#x1f393;二. 新增(Create)&#x1f393;三. 查询(Rertieve)&#x1f4d6;1. 全列查询&#x1f4d6;2. 指定列查询&#x1f4d6;3. 查询带有表达式&#x1f4d6;4. 起别名查询(as )&#x1f4d6; 5. 去重查询(distinct)&#x1f4d6;6. 排序…...

    Android NDK版本迭代与FFmpeg交叉编译完全指南

    在Android开发中&#xff0c;使用NDK(Native Development Kit)进行原生代码开发是一项常见需求&#xff0c;特别是当我们需要集成FFmpeg这样的多媒体处理库时。本文将深入分析Android NDK的版本迭代分界线&#xff0c;详细讲解FFmpeg交叉编译的注意事项&#xff0c;并提供完整的…...

    【Linux网络】Socket-UDP相关函数

    socket() 函数 这个函数的作用是创建一个 Socket 文件描述符&#xff0c;在客户端和服务器都可以使用。 #include <sys/socket.h> int socket(int domain, int type, int protocol);参数&#xff1a; domain&#xff1a;指定协议族&#xff0c;例如 AF_INET 代表 IPv4 …...

    最优化方法Python计算:有约束优化应用——线性Lasso回归预测器

    实际应用中&#xff0c;特征维度 n n n通常远大于样本容量 m m m&#xff08; n ≪ m n\ll m n≪m&#xff09;&#xff0c;这种高维小样本场景下特征数据可能含有对标签数据 y i y_i yi​的取值不必要的成分&#xff0c;甚至是噪声。此时&#xff0c;我们希望回归模型中的优化…...

    基础算法 —— 二分算法 【复习总结】

    1. 简介 1.1 原理 二分算法&#xff0c;顾名思义&#xff0c;关键在于二分&#xff0c;当我们求解的目标具有二段性时&#xff0c;我们就可以使用二分算法&#xff1a; 先根据待查找区间中点位置&#xff0c;判断结果会在左侧还是右侧&#xff0c;接下来&#xff0c;舍弃一半…...

    计算机网络常识:缓存、长短连接 网络初探、URL、客户端与服务端、域名操作 tcp 三次握手 四次挥手

    缓存&#xff1a; 缓存是对cpu&#xff0c;内存的一个节约&#xff1a;节约的是网络带宽资源 节约服务器的性能 资源的每次下载和请求都会造成服务器的一个压力 减少网络对资源拉取的延迟 这个就是浏览器缓存的一个好处 表示这个html页面的返回是不要缓存的 忽略缓存 需要每次…...

    OpenHarmony平台驱动开发(九),MIPI DSI

    OpenHarmony平台驱动开发&#xff08;九&#xff09; MIPI DSI 概述 功能简介 DSI&#xff08;Display Serial Interface&#xff09;是由移动行业处理器接口联盟&#xff08;Mobile Industry Processor Interface (MIPI) Alliance&#xff09;制定的规范&#xff0c;旨在降…...

    经济体制1

    一&#xff0e;计划经济体制与市场经济体制 1.计划经济又称指令型经济&#xff0c;是对生产和资源分配以及产品消费事先进行计划的经济体制。 市场经济体制是指依靠市场手段对资源进行配置的经济体制 注意&#xff1a; 计划与市场都是调节经济的手段&#xff0c;都属于资源配…...

    Spring AI 入门(持续更新)

    介绍 Spring AI 是 Spring 项目中一个面向 AI 应用的模块&#xff0c;旨在通过集成开源框架、提供标准化的工具和便捷的开发体验&#xff0c;加速 AI 应用程序的构建和部署。 依赖 <!-- 基于 WebFlux 的响应式 SSE 传输 --> <dependency><groupId>org.spr…...

    [ctfshow web入门] web58

    信息收集 if(isset($_POST[c])){$c $_POST[c];eval($c); }else{highlight_file(__FILE__); }这麽简单&#xff1f; 解题 好吧&#xff0c;还是我想得太简单了 把system禁用了。不是参数过滤&#xff0c;而是直接禁用&#xff0c;不管是间接还是直接调用system都不行&#x…...

    Python量化交易Backtrader技术指标的实现

    一、Backtrader技术指标概览 (一)Backtrader内置指标的优势 Backtrader内置的技术指标具有以下优势: 多样性:涵盖了常见的移动平均线、相对强弱指数(RSI)、布林带等多种指标,满足了不同交易者的需求。易用性:通过简单的函数调用即可在策略中添加和使用这些指标,无需…...

    蓝桥杯第十六届c组c++题目及个人理解

    本篇文章只是部分题目的理解&#xff0c;代码和思路仅供参考&#xff0c;切勿当成正确答案&#xff0c;欢迎各位小伙伴在评论区与博主交流&#xff01; 题目&#xff1a;2025 题目解析 核心提取 要求的数中至少有1个0、2个2、1个5 代码展示 #include<iostream> #incl…...

    ARM 芯片上移植 Ubuntu 操作系统详细步骤

    一、准备工作 &#xff08;一&#xff09;硬件准备 ARM 开发板&#xff1a;确保 ARM 开发板的型号与 Ubuntu 官方支持的 ARM 架构兼容&#xff0c;常见的 ARM 架构有 ARMv7、ARMv8 等。例如树莓派系列开发板&#xff0c;广泛用于 ARM 系统移植&#xff0c;其采用 ARM 架构。存…...

    能耗优化新引擎:EIOT平台助力企业降本增效

    安科瑞顾强 数字化转型的背景下&#xff0c;能源管理正加速向智能化、远程化方向演进。安科瑞电气推出的EIOT托管平台及ADW300系列4G无线计量仪表&#xff0c;通过云端技术与无线通信的深度融合&#xff0c;为用户打造了高效、便捷的远程能源监测与管理体系&#xff0c;助力企…...

    录播课视觉包装与转化率提升指南

    1. 封面设计黄金法则 1.1 程序员审美三要素 极客风配色方案 主色&#xff1a;深空灰(#2D2D2D) 代码蓝(#007BFF) 点缀色&#xff1a;终端绿(#28A745) 警告黄(#FFC107) 信息密度控制 核心标语≤9字&#xff08;如&#xff1a;"3天攻克分布式事务"&#xff09; 技…...

    Solidity语言基础:区块链智能合约开发入门指南

    一、Solidity概述 Solidity是以太坊生态系统中最重要的智能合约编程语言&#xff0c;由Gavin Wood于2014年提出。作为面向合约的高级语言&#xff0c;它结合了JavaScript、Python和C的语法特点&#xff0c;专为在以太坊虚拟机&#xff08;EVM&#xff09;上运行而设计。 核心…...

    QMK开发环境搭建指南:Eclipse和VS Code详解

    QMK开发环境搭建指南&#xff1a;Eclipse和VS Code详解 前言 各位键盘DIY爱好者们&#xff0c;今天跟大家分享如何搭建QMK固件开发环境。无论你是想定制自己的客制化键盘固件&#xff0c;还是对开源键盘固件开发感兴趣&#xff0c;这篇教程都能帮你搞定开发环境配置。本文将详…...

    Python pandas 向excel追加数据,不覆盖之前的数据

    最近突然看了一下pandas向excel追加数据的方法&#xff0c;发现有很多人出了一些馊主意&#xff1b; 比如用concat,append等方法&#xff0c;这种方法的会先将旧数据df_1读取到内存&#xff0c;再把新数据df_2与旧的合并&#xff0c;形成df_new,再覆盖写入&#xff0c;消耗和速…...

    spring中RequestContextHolder

    1、在 Spring 框架中&#xff0c; RequestAttributes attributes RequestContextHolder.getRequestAttributes(); 是获取当前请求上下文的核心方法。以下是其关键要点及注意事项&#xff1a; ‌一、核心机制‌ ‌作用原理‌ 通过 ThreadLocal 存储当前线程的请求属性对象 …...

    Kotlin 遍历

    在 Kotlin 中&#xff0c;遍历&#xff08;迭代&#xff09;是操作集合、数组、范围&#xff08;Range&#xff09;等数据结构的常见需求。Kotlin 提供了多种遍历方式&#xff0c;语法简洁且功能强大。以下是不同场景下的遍历方法总结&#xff0c;附代码示例&#xff1a; 一、…...

    Ubuntu Linux系统配置账号无密码sudo

    在Linux系统中&#xff0c;配置无密码sudo可以通过修改sudoers文件来实现。以下是具体的配置步骤 一、编辑sudoers文件 输入sudo visudo命令来编辑sudo的配置文件。visudo是一个专门用于编辑sudoers文件的命令&#xff0c;它会在保存前检查语法错误&#xff0c;从而防止可能的…...

    C# NX二次开发:判断两个体是否干涉和获取系统日志的UFUN函数

    大家好&#xff0c;今天要讲关于如何判断两个体是否干涉和获取系统日志的UFUN函数。 &#xff08;1&#xff09;UF_MODL_check_interference&#xff1a;这个函数的定义为根据单个目标体检查每个指定的工具体是否有干扰。 Defined in: uf_modl.h Overview Checks each sp…...

    若依项目图片显示问题

    图片显示异常问题 路径配置问题&#xff1a;前端图片路径配置错误&#xff0c;最初使用相对路径且未从根目录开始解析&#xff0c;导致浏览器根据当前页面 URL 解析路径出错。例如在用户信息展示页面&#xff0c;若当前页面 URL 为http://localhost:8088/user/profile&#xff…...

    线索二叉树

    一 概念 线索二叉树&#xff08;Threaded Binary Tree&#xff09;是一种对二叉树的优化结构&#xff0c;主要解决传统二叉树遍历时需要借助栈或递归&#xff08;额外空间开销&#xff09;的问题。通过利用节点中的空指针&#xff08;nullptr&#xff09;存储遍历过程中的前驱…...

    Git查看某个commit的改动

    在Git中查看特定commit的改动有多种方法&#xff0c;下面是几种常用的命令行方式&#xff1a; 1. 使用 git show 命令 这是最常用的方法&#xff0c;直接显示某个commit的详细信息和改动&#xff1a; git show <commit-hash> 例如&#xff1a; git show abc1234 也可…...

    es 里的Filesystem Cache 理解

    文章目录 背景问题1&#xff0c;Filesystem Cache 里放的是啥问题2&#xff0c;哪些查询它们会受益于文件系统缓存 问题3 查询分析 背景 对于es 优化来说常常看到会有一条结论给&#xff0c;给 JVM Heap 最多不超过物理内存的 50%&#xff0c;且不要超过 31GB&#xff08;避免…...

    2025年3月电子学会等级考试五级题——4、收费站在哪里

    文章目录 题目代码公式小结 题目 4、收费站在哪里 在一条高速公路上&#xff0c;如果已知 n 座收费站的位置 x1,x2,… ,xn&#xff08;不妨假设 0x1 ≤ x2 ≤ … ≤ xn&#xff09;&#xff0c;就很容易算出一共有 n(n-1)/2 个距离的值。而比较困难的问题是&#xff0c;在收集…...

    深入探索 JavaScript 中的模块对象

    引言 在现代 JavaScript 开发中&#xff0c;模块化编程是一项至关重要的技术。它允许开发者将代码拆分成多个独立的模块&#xff0c;每个模块专注于单一功能&#xff0c;从而提高代码的可维护性、可测试性和复用性。而模块对象则是模块化编程中的核心概念之一&#xff0c;它为…...

    R1-Searcher:用强化学习解锁大语言模型检索新能力!

    R1-Searcher&#xff1a;用强化学习解锁大语言模型检索新能力&#xff01; 大语言模型&#xff08;LLMs&#xff09;发展迅猛&#xff0c;却常因依赖内部知识而在复杂问题上“栽跟头”。今天解读的论文提出R1-Searcher框架&#xff0c;通过强化学习提升LLMs检索能力。它表现超…...

    LangChain框架-PromptTemplate 详解

    摘要 本文聚焦于 LangChain 框架中PromptTemplate提示词模板模块的深度解析,主要参考langchain_core.prompts源码模块与官方文档。系统梳理 LangChain 对提示词模板的封装逻辑与设计思路,旨在帮助读者构建全面、深入的知识体系,为高效运用LangChain 框架的提示词模板开发应用…...

    【Java ee 初阶】文件IO和操作(下)

    书接上文 文本操作的方法 String[] list() 返回 File 对象代表的目录下的所有文件名 File[] listFiles() 返回 File 对象代表的目录下的所有文件&#xff0c;以 File 对象表示 此处是针对File对象打印得到的效果&#xff08;调用了File的toString&#xff09; boolean …...

    Android7 Input(六)InputChannel

    概述: 本文讲述Android Input输入框架中 InputChannel的功能。从前面的讲述&#xff0c;我们知道input系统服务最终将输入事件写入了InputChannel&#xff0c;而input属于system_server进程&#xff0c;App属于另外一个进程&#xff0c;当Input系统服务想要把事件传递给App进行…...

    【Java ee初阶】初始网络

    一、IP地址 概念 IP地址主要用于标识网络主机、其他网络设备&#xff08;如路由器&#xff09;的网络地址。简单说&#xff0c;IP地址用于定位主机的网络地址。 就像我们发送快递一样&#xff0c;需要知道对方的收货地址&#xff0c;快递员才能将包裹送到目的地。 格式 IP…...

    LabVIEW 2019 与 NI VISA 20.0 安装及报错处理

    在使用 Windows 11 操作系统的电脑上&#xff0c;同时安装了 LabVIEW 2019 32 位和 64 位版本的软件。此前安装的 NI VISA 2024 Q1 版&#xff0c;该版本与 LabVIEW 2019 32 位和 64 位不兼容&#xff0c;之后重新安装了 NI VISA 20.0。从说明书来看&#xff0c;NI VISA 20.0 …...

    http协议理解

    文章目录 http协议理解基本概念HTTP版本演变版本编年史版本对比未来趋势 HTTP请求/响应结构请求报文响应报文HTTP方法分类对比方法选择原则必须遵守的约束 常见状态码HTTP头部字段HTTPSHTTPS 核心功能说明HTTPS 如何工作&#xff1f; HTTP特点补充知识点启用HTTP/2Nginx 中配置…...

    typecho中的Widget设计文档

    组成系统的最基本元素 什么是Widget Widget是组成Typecho的最基本元素&#xff0c;除了已经抽象出来的类库外&#xff0c;其它几乎所有的功能都会通过Widget来完成。在实践中我们发现&#xff0c;在博客这种小型但很灵活的系统中实施一些大型框架的思想是不合适的&#xff0c…...

    使用ESPHome烧录固件到ESP32-C3并接入HomeAssistant

    文章目录 一、安装ESPHome二、配置ESP32-C3控制灯1.主配置文件esp32c3-luat.yaml2.基础通用配置base.yaml3.密码文件secret.yaml4.围栏灯four_light.yaml5.彩灯rgb_light.yaml6.左右柱灯left_right_light.yaml 三、安装固件四、HomeAssistant配置ESPHome1.直接访问2.配置ESPHom…...

    基于STM32、HAL库的CH340N USB转UART收发器 驱动程序设计

    一、简介: CH340N是南京沁恒电子生产的一款USB转串口芯片,具有以下特点: 支持USB 2.0全速(12Mbps) 内置时钟,无需外部晶振 支持5V和3.3V电源电压 提供常用的MODEM联络信号 内置上电复位电路 支持Windows/Linux/Mac OSX等多平台驱动 体积小,SOP-8封装 二、硬件接口: CH…...

    Spring Boot Controller 如何处理HTTP请求体

    Spring Boot (通过Spring MVC) 提供了强大的机制来处理不同 Content-Type​ 的HTTP请求体。这主要依赖于 HttpMessageConverter​ 接口的各种实现&#xff0c;它们能够自动将请求体内容转换成Java方法参数。 一、核心机制&#xff1a;HttpMessageConverter​ Spring MVC会根据…...

    【deepseek教学应用】001:deepseek如何撰写教案并自动实现word排版

    本文讲述利用deepseek如何撰写教案并自动实现word高效完美排版。 文章目录 一、访问deepseek官网二、输入教案关键词三、格式转换四、word进一步排版 一、访问deepseek官网 官网&#xff1a;https://www.deepseek.com/ 进入主页后&#xff0c;点击【开始对话】&#xff0c;如…...

    【Spring Boot 多模块项目】@MapperScan失效、MapperScannerConfigurer 报错终极解决方案

    在使用 Spring Boot 构建多模块项目&#xff0c;集成 MyBatis-Plus 时&#xff0c;很多开发者会遇到类似如下启动报错&#xff1a; Error creating bean with name mapperScannerConfigurer ... Caused by: java.lang.IllegalArgumentException: Property basePackage is requ…...

    vue 中如何使用region?

    vue 中如何使用region&#xff1f; 在 Vue 文件中&#xff0c;你可以使用 //#region 和 //#endregion 注释来创建可折叠的代码区块&#xff08;类似于 C# 的 region&#xff09;。这可以显著提高大型 Vue 组件的可读性。 1. 基本用法 在 <script> 部分使用 <script&…...

    Spring Boot 启动原理的核心机制

    一、核心启动流程概览 Spring Boot 的启动流程可概括为 ​7 个关键阶段​&#xff1a; 1. 加载启动类 (Main Class) 2. 初始化 SpringApplication 实例 3. 加载配置 & 准备环境 (Environment) 4. 创建 ApplicationContext&#xff08;容器&#xff09; 5. 刷新容器&#…...

    【每天学习一点点】使用Python的pathlib模块分割文件路径

    使用Python的pathlib模块分割文件路径 pathlib模块&#xff08;Python 3.4&#xff09;提供了面向对象的文件系统路径操作方式&#xff0c;比传统的os.path更加直观和易用。以下是使用pathlib分割文件路径的几种方法&#xff1a; 基本路径分割 from pathlib import Path# 创…...

    Qt/C++面试【速通笔记八】—Qt的事件处理机制

    在Qt中&#xff0c;事件处理机制是应用程序与用户或系统交互的核心。通过事件处理&#xff0c;Qt能够响应用户的输入、窗口的变化、定时器的触发等各种情况。 1. 事件循环&#xff08;Event Loop&#xff09; 在Qt应用程序中&#xff0c;事件循环是事件处理机制的基础。事件循…...