QTextDocument 入门 一、QTextDocumentQTextDocument 是 Qt 中用于处理富文本文档的核心类,支持文本格式、图片、表格等复杂内容。1. QTextDocument 入门1.1 基本概念QTextDocument 是 Qt 中用于处理富文本内容的核心类,它提供了:结构化文本存储(段落、列表、表格等)文本格式支持(字体、颜色、对齐等)文档布局管理撤销/重做功能HTML/纯文本/Markdown 支持1.2 创建方式// 方式1:直接创建 QTextDocument *doc = new QTextDocument(parent); // 方式2:从QTextEdit获取 QTextEdit *editor = new QTextEdit; QTextDocument *doc = editor-document(); // 方式3:从内容创建 QTextDocument *doc = new QTextDocument("初始内容", parent);2. 核心属性表属性类型访问描述baseUrlQUrl读写解析相对URL的基础地址blockCountint只读文档中的文本块数量characterCountint只读文档字符总数defaultFontQFont读写默认字体设置documentMarginqreal读写文档页边距indentWidthqreal读写缩进宽度isEmptybool只读是否为空文档modifiedbool读写文档是否被修改pageSizeQSizeF读写页面尺寸textWidthqreal读写文本宽度限制titleQString读写文档标题undoRedoEnabledbool读写是否启用撤销/重做3. 重要方法分类3.1 内容操作// 设置/获取内容 void setPlainText(const QString text) QString toPlainText() const void setHtml(const QString html) QString toHtml() const void setMarkdown(const QString markdown) QString toMarkdown() const // 清空文档 void clear()3.2 文本查找QTextCursor find(const QString subString, const QTextCursor from = QTextCursor(), FindFlags flags = FindFlags()) const QTextCursor find(const QRegularExpression expr, const QTextCursor from = QTextCursor(), FindFlags flags = FindFlags()) const3.3 撤销/重做void undo() void redo() void clearUndoRedoStacks() bool isUndoAvailable() const bool isRedoAvailable() const3.4 文档结构// 获取文档部分 QTextBlock firstBlock() const QTextBlock lastBlock() const QTextFrame *rootFrame() const // 迭代器 QTextBlock begin() const QTextBlock end() const3.5 资源管理QVariant loadResource(int type, const QUrl name) void addResource(int type, const QUrl name, const QVariant resource)3.6 打印输出void drawContents(QPainter *painter, const QRectF rect = QRectF()) void print(QPagedPaintDevice *printer) const4. 信号系统信号描述contentsChanged()文档内容发生改变时触发contentsChange(int from, int charsRemoved, int charsAdded)详细内容变化信号undoAvailable(bool available)撤销状态变化redoAvailable(bool available)重做状态变化modificationChanged(bool changed)修改状态变化blockCountChanged(int newBlockCount)块数量变化cursorPositionChanged(const QTextCursor cursor)光标位置变化5. 实用示例5.1 基本使用QTextDocument doc; doc.setPlainText("Hello World!"); // 设置格式 QTextCursor cursor(doc); cursor.movePosition(QTextCursor::Start); QTextCharFormat fmt; fmt.setFontWeight(QFont::Bold); cursor.insertText("Formatted ", fmt);5.2 HTML处理doc.setHtml("bBold/b and iitalic/i text"); QString html = doc.toHtml();5.3 响应变化connect(doc, QTextDocument::contentsChanged, [](){ qDebug() "Document modified"; });6. 高级功能6.1 自定义文档布局class CustomLayout : public QAbstractTextDocumentLayout { /* 实现布局逻辑 */ }; doc-setDocumentLayout(new CustomLayout(doc));6.2 文本对象接口class CustomTextObject : public QObject, public QTextObjectInterface { /* 实现自定义文本对象 */ }; QTextCharFormat format; format.setObjectType(QTextFormat::UserObject + 1); doc-documentLayout()-registerHandler(format.objectType(), new CustomTextObject);7.300 DPI 下处理 QTextDocument 的 A4 尺寸当需要以 300 DPI (每英寸点数) 的高分辨率处理 QTextDocument 的 A4 纸张尺寸时,以下是详细的实现方法:1). A4 纸张尺寸计算 (300 DPI)// 标准 A4 尺寸 (毫米) const qreal a4WidthMM = 210.0; const qreal a4HeightMM = 297.0; // 毫米转英寸 const qreal mmToInch = 25.4; // 计算 300 DPI 下的像素尺寸 const qreal dpi = 300.0; qreal a4WidthPx = (a4WidthMM / mmToInch) * dpi; // ≈ 2480 像素 qreal a4HeightPx = (a4HeightMM / mmToInch) * dpi; // ≈ 3508 像素2). 设置 QTextDocument 为 A4 尺寸 (300 DPI)QTextDocument doc; // 方法1:直接设置像素尺寸 doc.setPageSize(QSizeF(a4WidthPx, a4HeightPx)); // 方法2:通过 QPrinter 获取精确尺寸 QPrinter printer(QPrinter::HighResolution); printer.setOutputFormat(QPrinter::PdfFormat); printer.setResolution(300); // 设置为 300 DPI printer.setPageSize(QPageSize::A4); // 使用打印机的页面矩形设置文档尺寸 QRectF pageRect = printer.pageRect(QPrinter::DevicePixel); doc.setPageSize(pageRect.size());3). 处理边距问题 (300 DPI)// 设置打印边距 (毫米) printer.setPageMargins(QMarginsF(15, 15, 15, 15), QPageLayout::Millimeter); // 获取实际可打印区域 (300 DPI) QRectF printableArea = printer.pageRect(QPrinter::DevicePixel); // 计算边距像素值 qreal leftMarginPx = (15 / mmToInch) * dpi; // ≈ 177 像素 qreal topMarginPx = (15 / mmToInch) * dpi; // ≈ 177 像素 qreal rightMarginPx = (15 / mmToInch) * dpi; // ≈ 177 像素 qreal bottomMarginPx = (15 / mmToInch) * dpi; // ≈ 177 像素 // 设置文档内容区域 doc.setDocumentMargin(0); // 先清除默认边距 doc.setPageSize(QSizeF( a4WidthPx - leftMarginPx - rightMarginPx, a4HeightPx - topMarginPx - bottomMarginPx ));4). 内容布局与分页计算 (300 DPI)// 获取文档总高度 qreal totalHeight = doc.documentLayout()-documentSize().height(); // 计算可打印区域高度 qreal printableHeight = printableArea.height(); // 计算页数 int pageCount = qCeil(totalHeight / printableHeight); // 获取每页的精确位置 for (int i = 0; i pageCount; ++i) { qreal pageTop = i * printableHeight; qreal pageBottom = (i + 1) * printableHeight; // 处理分页逻辑... }5). 字体大小与分辨率适配 (300 DPI)// 设置适合 300 DPI 的字体大小 QFont font; font.setFamily("Arial"); // 72pt 在 300 DPI 下会很大 (1pt = 1/72 inch) // 12pt 在 300 DPI 下的像素大小: (12/72)*300 = 50 像素 font.setPointSizeF(12.0); // 标准印刷常用大小 // 应用到文档 QTextCursor cursor(doc); QTextCharFormat format; format.setFont(font); cursor.setCharFormat(format);6). 导出为 PDF (保持 300 DPI)QPrinter printer(QPrinter::HighResolution); printer.setOutputFormat(QPrinter::PdfFormat); printer.setOutputFileName("output.pdf"); printer.setResolution(300); printer.setPageSize(QPageSize::A4); // 打印文档 doc.print(printer);7). 实际应用示例void createHighResPdf() { // 初始化文档 QTextDocument doc; // 设置 300 DPI A4 尺寸 const qreal dpi = 300.0; const qreal mmToInch = 25.4; QSizeF a4Size(210.0/mmToInch*dpi, 297.0/mmToInch*dpi); // 设置边距 (15mm) const qreal marginPx = 15.0/mmToInch*dpi; doc.setPageSize(QSizeF(a4Size.width()-2*marginPx, a4Size.height()-2*marginPx)); // 设置内容 QTextCursor cursor(doc); QFont font("Times New Roman", 12); // 12pt QTextCharFormat format; format.setFont(font); cursor.setCharFormat(format); cursor.insertText("300 DPI 高分辨率文档示例\n\n"); // 导出PDF QPrinter printer(QPrinter::HighResolution); printer.setOutputFormat(QPrinter::PdfFormat); printer.setOutputFileName("highres_doc.pdf"); printer.setResolution(300); printer.setPageSize(QPageSize::A4); printer.setPageMargins(QMarginsF(15, 15, 15, 15), QPageLayout::Millimeter); doc.print(printer); }8. 中文乱码问题在 QTextDocument 中显示或打印包含特殊字符(如 m³/a)时出现乱码,通常是由于编码问题导致的。以下是几种解决方案:1). 使用 HTML 实体编码(推荐)QTextDocument doc; doc.setHtml("msup3;/a"); // 使用HTML实体表示上标32). 使用 Unicode 字符QTextDocument doc; doc.setPlainText("m\u00B3/a"); // \u00B3是上标3的Unicode编码3). 确保使用 UTF-8 编码QTextDocument doc; doc.setPlainText(QString::fromUtf8("m³/a"));4). 打印时设置编码QTextDocument doc; doc.setHtml("m³/a"); QPrinter printer; QPrintDialog dialog(printer); if (dialog.exec() == QDialog::Accepted) { // 确保使用UTF-8编码 QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); doc.print(printer); }示例代码:#include QTextDocument #include QPrinter #include QPrintDialog #include QTextCodec void printDocument() { QTextDocument doc; // 方法1: HTML实体 //doc.setHtml("msup3;/a"); // 方法2: Unicode // doc.setPlainText("m\u00B3/a"); // 方法3: UTF-8 doc.setPlainText(QString::fromUtf8("m³/a")); // 方法4: HTML sup标签 // doc.setHtml("msup3/sup/a"); QPrinter printer; QPrintDialog dialog(printer); if (dialog.exec() == QDialog::Accepted) { QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); doc.print(printer); } }9. 性能优化技巧批量操作:在大量修改前调用blockSignals(true),完成后恢复资源管理:对大型文档使用分页加载格式重用:复用 QTextFormat 对象减少内存分配布局控制:合理设置 textWidth 和页面尺寸二、QTextCursorQTextCursor 是 Qt 框架中用于操作 QTextDocument 的核心类,提供了对富文本内容的编辑、选择和格式控制功能。它类似于文本编辑器中的光标,可以移动、插入、删除文本,并控制文本格式。1. QTextCursor 基本概念1.1 主要用途文本插入和删除:在 QTextDocument 中插入或删除文本。文本选择:选择文本范围,进行复制、剪切或格式修改。格式控制:设置字符格式(字体、颜色等)和段落格式(对齐、缩进等)。表格和列表操作:插入表格、列表,并控制其结构。1.2 创建 QTextCursor// 方式1:基于 QTextDocument 创建 QTextDocument *doc = new QTextDocument; QTextCursor cursor(doc); // 方式2:基于现有 QTextCursor 复制 QTextCursor anotherCursor(cursor); // 方式3:基于 QTextEdit 获取(适用于 GUI 应用) QTextEdit *textEdit = new QTextEdit; QTextCursor editCursor = textEdit-textCursor();2. QTextCursor 属性QTextCursor 本身没有直接可访问的属性(如property()),但可以通过方法获取或修改其状态:属性(概念)获取方法设置方法位置position()setPosition(int pos)是否有选择hasSelection()clearSelection()选择范围selectionStart(),selectionEnd()setPosition(pos, mode)当前块(段落)block()movePosition()当前字符格式charFormat()setCharFormat()当前段落格式blockFormat()setBlockFormat()是否可撤销/重做isUndoAvailable()/isRedoAvailable()undo()/redo()3. QTextCursor 常用方法3.1 光标移动方法说明movePosition(MoveOperation op, MoveMode mode = MoveAnchor, int n = 1)移动光标(如StartOfLine,EndOfDocument)setPosition(int pos, MoveMode mode = MoveAnchor)设置光标位置atStart(),atEnd()是否在文档开头/结尾atBlockStart(),atBlockEnd()是否在段落开头/结尾示例:cursor.movePosition(QTextCursor::StartOfLine); // 移动到行首 cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor); // 选择到文档末尾3.2 文本操作方法说明insertText(const QString text)插入纯文本insertText(const QString text, const QTextCharFormat format)插入带格式的文本insertHtml(const QString html)插入 HTMLinsertFragment(const QTextDocumentFragment fragment)插入文档片段