Qt为解析、呈现、操作和编辑富文本提供了广泛的类集合:
- QAbstarctTextDocumentLayout :用于实现QTextDocuments自定义布局的抽象基类。
- QFont:指定用于绘制文本的字体的查询。
- QPlainTextDocumentLayout:实现QTextDocument的纯文本布局。
- QPlainTextEdit:用于编辑和修改纯文本的控件。
- QSyntaxHignlignter:允许定义语法突出显示规则,此外还可以使用该类查询文档的当前格式或用户数据。
- QTextBlock:QTextDocument中文本片段的容器。
- QTextBlock::iterator:iterator类提供了一个迭代器,用于读取QTextBlock的内容。
- QTextBlockFormat:格式化QTextDocument中文本块的信息。
- QTextBlockGroup:QTextDocument中文本块的容器。
- QTextBlockUserData:用于将自定义数据与文本块关联。
- QTextBrowser:富文本浏览器与超文本导航。
- QTextCharFormat:格式化QTextDocument中字符的信息。
- QTextCursor:提供一个API来访问和修改QTextDocuments。
- QTextDocument:格式化文本文档。
- QTextDocumentFragment:表示来自QTextDocument的一段格式化文本。
- QTextDocumentWriter:用于将QTextDocument写入文件或其他设备的与格式无关的接口。
- QTextEdit:用于编辑和显示纯文本和富文本的小部件。
- QTextFormat:QTextDocument的格式化信息。
- QTextFragment:在QTextDocument中保存一段具有单个QTextCharFormat的文本。
- QTextFrame:用于组织富文本内容,可以将富文本内容分割成多个段落(QTextBlock)或区块(QTextFrame)。每个QTextFrame可以包含一个或多个QTextBlock,并可以嵌套其他QTextFrame。
- QTextFrame::iterator:用于读取QTextFrame内容的迭代器。
- QTextFrameFormat:QTextDocument中QTextFrame的格式化信息。
- QTextImageFormat:在QTextDocument中格式化图像信息。
- QTextInLineObject:表示QAbstractTextDocumentLayout中的内联对象及其实现。
- QTextLayout:用于布局和渲染文本。
- QTextLength:封装QTextDocument中使用的不同类型的长度。
- QTextLine:表示QTextLayout中的一行文本。
- QTextList:QTextDocument中的装饰项列表。
- QTextListFormat:格式化QTextDocument中列表的信息。
- QTextObject:可以将QTextDocument的各个部分组合在一起的不同类型对象的基类。
- QTextOption:一般富文本属性的描述。
- QTextTable:表示QTextDocument中的一个表。
- QTextTableCell:表示qtextttable中单元格的属性。
- QTextTableCellFormat:格式化QTextDocument中表格单元格的信息。
- QTextTableFormat:格式化QTextDocument中表的信息。
富文本文档结构
说明:文档的“顶层”可以按照所示的方式填充。每个文档总是包含一个根框架,并且根框架总是包含至少一个文本块。对于具有某些文本内容的文档,根框架通常包含一系列块和其他元素。在文档中,框架和表的序列总是由文本块分隔,即使文本块不包含任何信息。这确保了新元素总是可以插入到现有结构之间。
使用QTextCursor或使用编辑器小部件(如qtexttedit)以编程方式创建新元素并将其插入文档。元素在创建时可以被赋予特定的格式;否则,它们将采用元素的游标当前格式。
富文本文档
QTextDocument对象包含构造富文本文档所需的所有信息。文本文档可以以两种互补的方式访问:作为编辑器使用的线性缓冲区,以及作为对布局引擎有用的对象层次结构。在分层文档模型中,对象通常对应于框架、表和列表等可视元素。在较低的层次上,这些元素描述诸如文本样式和对齐等属性。文档的线性表示用于编辑和操作文档的内容。虽然QTextEdit可以很容易地显示和编辑富文本,但文档也可以独立于任何编辑器部件使用,例如:
QTextDocument *newDocument = new QTextDocument;
或者可以从现有的编辑器中提取:
QTextEdit *editor = new QTextEdit;
QTextDocument *editorDocument = editor->document();
这种灵活性使应用程序能够处理多个富文本文档,而不需要多个编辑器小部件的开销,也不需要以某种中间格式存储文档。一个空文档包含一个根框架,根框架本身包含一个空文本块。框架提供文档各部分之间的逻辑分离,但也具有决定它们在呈现时如何显示的属性。表是一种特殊类型的框架,它由许多单元格组成,排列成行和列,每个单元格都可以包含进一步的结构和文本。表格提供了管理和布局特性,允许创建灵活的单元格配置。文本块包含文本片段,每个文本片段指定文本和字符格式信息。文本属性是在字符级和块级定义的。在字符级别,可以指定字体族、文本颜色和字体粗细等属性。块级别属性控制文本的高级外观和行为,例如文本流的方向、对齐方式和背景颜色。不直接操作文档结构。编辑是通过基于游标的界面执行的。文本光标界面自动将新的文档元素插入根框架,并确保在必要的地方用空块填充。
通过以下方式获得根框架:
QTextDocument *textDocument;
QTextFrame *root = textDocument->rootFrame();
在导航文档结构时,从根框架开始很有用,因为它提供了对整个文档结构的访问。
文档元素
富文本文档通常由段落、框架、表格和列表等常见元素组成。这些在QTextDocument中由QTextBlock, QTextFrame, qtextttable和QTextList类表示。与文档中的其他元素不同,图像由特殊格式的文本片段表示。这使它们能够以格式与周围的文本内联放置。文档中的基本结构构建块是QTextBlock和QTextFrame。块本身包含富文本片段(QTextFragment),但这些片段并不直接影响文档的高层结构。可以将其他文档元素组合在一起的元素通常是qtexttobject的子类,分为两类:将文本块组合在一起的元素是QTextBlockGroup的子类,将框架和其他元素组合在一起的元素是QTextFrame的子类。
Text Blocks
文本块由QTextBlock类提供。
文本块将具有不同字符格式的文本片段组合在一起,用于表示文档中的段落。每个块通常包含许多不同样式的文本片段。在将文本插入文档时创建片段,在编辑文档时添加更多片段。文档拆分、合并和删除片段,以有效地表示块中不同样式的文本。
可以通过使用QTextBlock::迭代器遍历来检查给定块中的片段:
QTextBlock::iterator it;
for (it = currentBlock.begin(); !(it.atEnd()); ++it) {
QTextFragment currentFragment = it.fragment();
if (currentFragment.isValid())
processFragment(currentFragment);
}
块也用于表示列表项。因此,块可以定义自己的字符格式,其中包含关于块级装饰的信息,例如用于列表项的项目符号类型。块本身的格式由QTextBlockFormat类描述,并描述诸如文本对齐、缩进和背景颜色等属性。
虽然给定的文档可能包含复杂的结构,但是一旦我们在文档中引用了一个有效的块,我们就可以按照它们被写入的顺序在每个文本块之间导航:
QTextBlock currentBlock = textDocument->begin();
while (currentBlock.isValid()) {
processBlock(currentBlock);
currentBlock = currentBlock.next();
}
当只想从文档中提取富文本时,此方法非常有用,因为它忽略了框架、表和其他类型的结构。
QTextBlock提供了比较操作符,使操作块变得更容易:operator==()和operator!=()用于测试两个块是否相同,operator<()用于确定哪个块首先出现在文档中。
Frames
框架由QTextFrame类提供。
文本框架将文本块和子框架组合在一起,创建比段落大的文档结构。框架的格式指定了它在页面上的呈现和定位方式。框架要么插入到文本流中,要么漂浮在页面的左侧或右侧。每个文档都包含一个根框架,其中包含所有其他文档元素。因此,除了根帧之外的所有帧都有一个父帧。
由于文本块用于分隔其他文档元素,因此每个框架将始终包含至少一个文本块和零个或多个子框架。我们可以通过使用QTextFrame::迭代器遍历框架的子元素来检查框架的内容:
QDomElement frameElement = ...
QTextFrame::iterator it;
for (it = frame->begin(); !(it.atEnd()); ++it) {
QTextFrame *childFrame = it.currentFrame();
QTextBlock childBlock = it.currentBlock();
if (childFrame)
processFrame(frameElement, childFrame);
else if (childBlock.isValid())
processBlock(frameElement, childBlock);
}
注意,迭代器同时选择帧和块,因此有必要检查它引用的是哪个。这允许我们在逐帧的基础上浏览文档结构,但如果需要,仍然可以访问文本块。QTextBlock::iterator和QTextFrame::iterator类都可以互补地从文档中提取所需的结构。
Tables
表由qtextttable类提供。
表是按行和列排列的单元格集合。每个表格单元格都是一个文档元素,具有自己的字符格式,但它也可以包含其他元素,如框架和文本块。在构造表或添加额外的行或列时,将自动创建表单元格。它们也可以在表之间移动。
QTextTable是QTextFrame的子类,因此表在文档结构中被视为框架。对于我们在文档中遇到的每一个帧,我们可以测试它是否代表一个表,并以不同的方式处理它:
QDomElement frameElement = ...
QTextFrame::iterator it;
for (it = frame->begin(); !(it.atEnd()); ++it) {
QTextFrame *childFrame = it.currentFrame();
QTextBlock childBlock = it.currentBlock();
if (childFrame) {
QTextTable *childTable = qobject_cast<QTextTable*>(childFrame);
if (childTable)
processTable(frameElement, childTable);
else
processFrame(frameElement, childFrame);
} else if (childBlock.isValid())
processBlock(frameElement, childBlock);
}
可以通过遍历行和列来检查现有表中的单元格。
for (int row = 0; row < table->rows(); ++row) {
for (int column = 0; column < table->columns(); ++column) {
QTextTableCell tableCell = table->cellAt(row, column);
processTableCell(tableCell);
}
}
Lists
列表由QTextList类提供。
列表是按通常方式格式化的文本块序列,但也提供标准的列表装饰,如项目符号和枚举项。列表可以嵌套,如果列表的格式指定了非零缩进,列表将被缩进。
我们可以通过列表中的索引来引用每个列表项:
for (int index = 0; index < list->count(); ++index) {
QTextBlock listItem = list->item(index);
processListItem(listItem);
}
因为QTextList是QTextBlockGroup的子类,所以它不会将列表项分组为子元素,而是提供各种功能来管理它们。这意味着我们在遍历文档时发现的任何文本块实际上都可能是一个列表项。我们可以使用以下代码确保正确识别列表项:
QTextFrame::iterator it;
for (it = frame->begin(); !(it.atEnd()); ++it) {
QTextBlock block = it.currentBlock();
if (block.isValid()) {
QTextList *list = block.textList();
if (list) {
int index = list->itemNumber(block);
processListItem(list, index);
}
}
}
Images
QTextDocument中的图像由文本片段表示,这些文本片段通过资源机制引用外部图像。使用光标界面创建图像,稍后可以通过更改图像文本片段的字符格式来修改图像:
if (fragment.isValid()) {
QTextImageFormat newImageFormat = fragment.charFormat().toImageFormat();
if (newImageFormat.isValid()) {
newImageFormat.setName(":/images/newimage.png");
QTextCursor helper = cursor;
helper.setPosition(fragment.position());
helper.setPosition(fragment.position() + fragment.length(),
QTextCursor::KeepAnchor);
helper.setCharFormat(newImageFormat);
}
}
表示图像的片段可以通过迭代包含图像的文本块中的片段来找到。
注:本文翻译自Qt官方文档。