警告
本节包含从C++自动翻译到Python的代码片段,可能包含错误。
富文本文档结构¶
文本文件由QTextDocument类表示,该类包含有关文档内部表示、结构的信息,并跟踪修改以提供撤销/重做功能。
文本文档的结构化表示将其内容呈现为文本块、框架、表格和其他对象的层次结构。这些为文档提供了逻辑结构,并描述了它们的内容将如何显示。通常,框架和表格用于分组其他结构,而文本块包含实际的文本信息。
新元素是通过编程方式创建并插入到文档中的使用QTextCursor或通过使用编辑器小部件(如QTextEdit)。元素在创建时可以赋予特定的格式;否则,它们将采用光标当前为该元素设置的格式。
基本结构
文档的“顶层”可能会以所示的方式填充。每个文档始终包含一个根框架,并且该框架始终包含至少一个文本块。
对于具有一些文本内容的文档,根框架通常包含一系列块和其他元素。
在文档中,框架和表格的序列始终由文本块分隔,即使这些文本块不包含任何信息。这确保了新元素始终可以插入到现有结构之间。
在本章中,我们将查看富文本文档中使用的每个结构元素,概述它们的功能和用途,并展示如何检查它们的内容。文档编辑在The QTextCursor Interface中描述。
富文本文档¶
QTextDocument 对象包含构建富文本文档所需的所有信息。文本文档可以通过两种互补的方式访问:作为编辑器使用的线性缓冲区,以及作为对布局引擎有用的对象层次结构。在层次文档模型中,对象通常对应于视觉元素,如框架、表格和列表。在较低层次上,这些元素描述了文本样式和对齐等属性。文档的线性表示用于编辑和操作文档内容。
尽管QTextEdit使得显示和编辑富文本变得容易,文档也可以独立于任何编辑器小部件使用,例如:
newDocument = QTextDocument()
或者,它们可以从现有的编辑器中提取:
editor = QTextEdit() editorDocument = editor.document()
这种灵活性使应用程序能够处理多个富文本文档,而无需多个编辑器小部件的开销,也不需要将文档存储在某些中间格式中。
一个空文档包含一个根框架,该框架本身包含一个空的文本块。框架提供了文档各部分之间的逻辑分离,但也具有决定它们在渲染时如何显示的属性。表格是一种特殊类型的框架,由多个单元格组成,排列成行和列,每个单元格可以包含更多的结构和文本。表格提供了管理和布局功能,允许创建灵活的单元格配置。
文本块包含文本片段,每个片段都指定了文本和字符格式信息。文本属性在字符级别和块级别都有定义。在字符级别,可以指定诸如字体家族、文本颜色和字体粗细等属性。块级别属性控制文本的高级外观和行为,例如文本流动方向、对齐方式和背景颜色。
文档结构不直接操作。编辑是通过基于光标的界面进行的。文本光标界面会自动将新文档元素插入到根框架中,并确保在必要时用空块填充。
我们通过以下方式获取根框架:
editorDocument = editor.document() root = editorDocument.rootFrame()
在浏览文档结构时,从根框架开始非常有用,因为它提供了对整个文档结构的访问。
文档元素¶
富文本文档通常由段落、框架、表格和列表等常见元素组成。这些元素在QTextDocument中由QTextBlock、QTextFrame、QTextTable和QTextList类表示。与文档中的其他元素不同,图像由特殊格式的文本片段表示。这使得它们可以与周围的文本一起格式化放置。
文档中的基本结构构建块是QTextBlock和QTextFrame。块本身包含富文本片段(QTextFragment),但这些片段并不直接影响文档的高级结构。
可以将其他文档元素分组的元素通常是QTextObject的子类,并分为两类:将文本块分组的元素是QTextBlockGroup的子类,而将框架和其他元素分组的元素是QTextFrame的子类。
文本块¶
文本块由QTextBlock类提供。
文本块将具有不同字符格式的文本片段组合在一起,用于表示文档中的段落。每个块通常包含多个具有不同样式的文本片段。当文本插入文档时会创建片段,编辑文档时会添加更多片段。文档会拆分、合并和删除片段,以有效地表示块中文本的不同样式。
可以通过使用iterator来遍历块的内部结构,从而检查给定块中的片段:
QTextBlock.iterator it for it in currentBlock: currentFragment = it.fragment() if currentFragment.isValid(): processFragment(currentFragment)
块也用于表示列表项。因此,块可以定义自己的字符格式,这些格式包含有关块级装饰的信息,例如用于列表项的符号类型。块本身的格式由QTextBlockFormat类描述,并描述了诸如文本对齐、缩进和背景颜色等属性。
尽管给定的文档可能包含复杂的结构,但一旦我们有了文档中有效块的引用,我们就可以按照它们被写入的顺序在每个文本块之间导航:
currentBlock = textDocument.begin() while currentBlock.isValid(): processBlock(currentBlock) currentBlock = currentBlock.next()
当您只想从文档中提取富文本时,此方法非常有用,因为它会忽略框架、表格和其他类型的结构。
QTextBlock 提供了比较运算符,使得操作块变得更加容易:operator==() 和 operator!=() 用于测试两个块是否相同,而 operator 用于确定哪个块在文档中先出现。
框架¶
框架由QTextFrame类提供。
文本框架将文本块和子框架组合在一起,创建比段落更大的文档结构。框架的格式指定了它如何在页面上渲染和定位。框架要么插入到文本流中,要么浮动在页面的左侧或右侧。每个文档包含一个根框架,该框架包含所有其他文档元素。因此,除根框架外,所有框架都有一个父框架。
由于文本块用于分隔其他文档元素,每个框架将始终包含至少一个文本块,以及零个或多个子框架。我们可以通过使用iterator来遍历框架的子元素来检查框架的内容:
QTextFrame.iterator it for it in frame: childFrame = it.currentFrame() childBlock = it.currentBlock() if childFrame: processFrame(childFrame) elif childBlock.isValid(): processBlock(childBlock)
请注意,迭代器选择的是帧和块,因此需要检查它指的是哪一个。这使我们能够逐帧导航文档结构,同时在需要时仍然可以访问文本块。iterator 和 iterator 类可以以互补的方式使用,以从文档中提取所需的结构。
表格¶
表格由QTextTable类提供。
表格是由排列成行和列的单元格组成的集合。每个表格单元格都是一个具有自己字符格式的文档元素,但它也可以包含其他元素,如框架和文本块。表格单元格在构建表格时或添加额外的行或列时自动创建。它们也可以在表格之间移动。
QTextTable 是 QTextFrame 的一个子类,因此表格在文档结构中像框架一样被处理。对于我们在文档中遇到的每个框架,我们可以测试它是否代表一个表格,并以不同的方式处理它:
QTextFrame.iterator it for it in frame: childFrame = it.currentFrame() childBlock = it.currentBlock() if childFrame: childTable = QTextTable(childFrame) if childTable: processTable(childTable) else: processFrame(childFrame) elif childBlock.isValid(): processBlock(childBlock)
可以通过遍历行和列来检查现有表格中的单元格。
for row in range(0, table.rows()): for column in range(0, table.columns()): tableCell = table.cellAt(row, column) processTableCell(tableCell)
列表¶
列表由QTextList类提供。
列表是文本块的序列,这些文本块以通常的方式格式化,但也提供了标准的列表装饰,如项目符号和编号项。列表可以嵌套,如果列表的格式指定了非零缩进,则列表将被缩进。
我们可以通过列表中的索引来引用每个列表项:
for index in range(0, list.count()): listItem = list.item(index) processListItem(listItem)
由于 QTextList 是 QTextBlockGroup 的子类,它不会将列表项作为子元素进行分组,而是提供了各种管理它们的函数。这意味着我们在遍历文档时找到的任何文本块实际上可能是一个列表项。我们可以通过使用以下代码确保正确识别列表项:
QTextFrame.iterator it for it in frame: block = it.currentBlock() if block.isValid(): list = block.textList() if list: index = list.itemNumber(block) processListItem(list, index)
图片¶
QTextDocument 中的图像通过文本片段表示,这些片段通过资源机制引用外部图像。图像是使用光标接口创建的,并且可以通过更改图像文本片段的字符格式来稍后修改:
if fragment.isValid(): newImageFormat = fragment.charFormat().toImageFormat() if newImageFormat.isValid(): newImageFormat.setName(":/images/newimage.png") helper = cursor helper.setPosition(fragment.position()) helper.setPosition(fragment.position() + fragment.length(), QTextCursor.KeepAnchor) helper.setCharFormat(newImageFormat)
表示图像的片段可以通过遍历包含图像的文本块中的片段来找到。
