文本文档由 QTextDocument 类表示,该类包含有关文档内部表示、结构的信息,并跟踪修改以提供撤消/回撤功能。
每个文档始终包含一个根框架,并且始终包含至少一个文本块。
框架/表格总是由文档中的文本块分隔,即使文本块不包含任何信息。这确保了新元素始终可以插入现有结构之间。
富文本文档通常由文本块(也叫段落)(QTextBlock)、框架(QTextFrame)、表格(QTextTable)、列表(QTextList)等常见元素组成。
文档中的基本结构构建元素是 QTextBlock 和 QTextFrame。QTextBlock 本身包含富文本片段(QTextFragment),但这些片段不会直接影响文档的高级结构。
可以使用 QTextObject 的子类将其他文档元素分组:
文本块将具有不同字符格式的文本片段组合在一起,用于表示文档中的段落。每个块通常包含多个具有不同样式的文本片段。
可以通过使用 QTextBlock::iterator 遍历块的内部结构来检查给定块中的片段:
- QTextDocument * docment = ui->textEdit->document();
- QTextBlock block = docment->findBlock(0);
- for (QTextBlock::iterator it = block.begin(); !(it.atEnd()); ++it)
- {
- QTextFragment currentFragment = it.fragment();
- if (currentFragment.isValid())
- {
- qDebug()<
text(); - }
- }
按顺序遍历文本块:
- QTextBlock currentBlock = docment->begin();
- while (currentBlock.isValid())
- {
- //...
- currentBlock = currentBlock.next();
- }
文本框架将文本块和子框架组合在一起,创建大于段落范围的文档结构。
每个框架含至少一个文本块和大于等于零个子框架。
每个文档都有一个包含所有其他文档元素的根框架。因此,除根框架外的所有框架都具有父框架。
可使用 QTextFrame::iterator 遍历框架的子元素:
- QTextDocument * docment = ui->textEdit->document();
- QTextFrame * rootFrame = docment->rootFrame();
- for (QTextFrame::iterator it = rootFrame->begin(); !(it.atEnd()); ++it)
- {
- QTextFrame *childFrame = it.currentFrame();
- QTextBlock childBlock = it.currentBlock();
-
- if (childFrame)
- {
- //...
- }
- else if (childBlock.isValid())
- {
- //...
- }
- }
表格是按行和列排列的单元格集合。每个单元格都是一个具有字符格式的文档元素,但它也可以包含其他元素,如框架和文本块。
QTextTable 是 QTextFrame 的子类,因此表格在文档结构中被视为框架。
对于文档中遇到的每个框架,可以测试它是否表示一个表格,并以不同的方式处理它:
- QTextDocument * docment = ui->textEdit->document();
- QTextFrame * rootFrame = docment->rootFrame();
- for (QTextFrame::iterator it = rootFrame->begin(); !(it.atEnd()); ++it)
- {
- QTextFrame *childFrame = it.currentFrame();
- QTextBlock childBlock = it.currentBlock();
-
- if (childFrame)
- {
- if (QTextTable *childTable = qobject_cast
(childFrame)) - {
- //...
- }
- else
- {
- //...
- }
- }
- else if (childBlock.isValid())
- {
- //...
- }
- }
可以通过遍历行和列来检查现有表中的单元格。
- for (int row = 0; row < table->rows(); ++row)
- {
- for (int column = 0; column < table->columns(); ++column)
- {
- QTextTableCell tableCell = table->cellAt(row, column);
- //...
- }
- }
列表通常以格式化方式展示文本块序列。
列表可以嵌套和设置缩进。
可以通过列表中的索引来引用每个列表项:
- QTextDocument * docment = ui->textEdit->document();
- QTextBlock block = docment->findBlock(0);
- if (QTextList * list = block.textList())
- {
- for (int index = 0; index < list->count(); ++index)
- {
- QTextBlock listItem = list->item(index);
- //...
- }
- }
QTextList 是 QTextBlockGroup(可管理文本块分组) 的子类,QTextList 仅为它的列表项提供管理功能,而没有把列表项作为它的子项。
即在遍历文档时发现的任何文本块实际上都可能是列表项。可以通过以下代码确保正确识别列表项:
- QTextDocument * docment = ui->textEdit->document();
- QTextFrame * rootFrame = docment->rootFrame();
- for (QTextFrame::iterator it = rootFrame->begin(); !(it.atEnd()); ++it)
- {
- QTextBlock block = it.currentBlock();
- if (block.isValid())
- {
- if (QTextList *list = block.textList())
- {
- int index = list->itemNumber(block);
- //processListItem(list, index);
- }
- }
- }
QTextCursor 提供了一个基于光标的编辑方式,允许在字符级别操纵 QTextDocument 的内容。
光标会跟踪其在父文档中的位置,并可以报告有关周围结构的信息,例如包围的文本块、框架、表格或列表。
一系列编辑操作可以打包在一起,以便可以在一个动作中一起回放或撤消。选择包含光标的内容:
- cursor.beginEditBlock();
- cursor.movePosition(QTextCursor::StartOfWord);
- cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
- cursor.endEditBlock();
如果编辑操作未分组,文档将自动记录各个操作,以便以后可以撤消这些操作。
可以使用多个光标同时编辑同一个文档,尽管用户在编辑小部件中只能看到一个光标。
QTextDocument 确保每个光标正确写入文本,并且不会干扰其他光标。
文档的布局仅在要在设备上显示时相关。
每个文档的布局都由 QAbstractTextDocumentLayout 类的子类管理。
QTextLayout 用法示例:
- #include "widget.h"
- #include
- #include
-
- Widget::Widget(QWidget *parent)
- : QWidget(parent)
- {
- auto font = this->font();
- font.setPixelSize(18);
- setFont(font);
- }
-
- Widget::~Widget()
- {
- }
-
- void Widget::paintEvent(QPaintEvent *event)
- {
- auto rect = event->rect();
- QTextLayout textLayout("黄河之水天上来,奔流到海不复回", this->font());
- qreal margin = 40;
- qreal radius = qMin(rect.width()/2.0, rect.height()/2.0) - margin;
-
- QPainter painter(this);
- painter.setRenderHint(QPainter::Antialiasing);
- painter.fillRect(rect, Qt::white);
- painter.setBrush(QBrush(Qt::black));
- painter.setPen(QPen(Qt::black));
- painter.setBrush(QBrush(QColor("#a6ce39")));
- painter.setPen(QPen(Qt::black));
- painter.translate(rect.center());
- painter.drawEllipse(QPointF(0,0),radius,radius);
-
- painter.setPen(QPen(Qt::red,5));
- for(int i = 0;i < 14;++i)
- {
- auto angle = 25.0 * i;
- auto x = cos(qDegreesToRadians(angle)) * (radius + 20);
- auto y = -sin(qDegreesToRadians(angle)) * (radius + 20);
- painter.drawPoint(x,y);
- }
-
- textLayout.beginLayout();
- auto angle{0.0f};
- while (true)
- {
- QTextLine line = textLayout.createLine();
- if (!line.isValid())
- break;
-
- auto x = cos(qDegreesToRadians(angle)) * (radius + 20);
- auto y = -sin(qDegreesToRadians(angle)) * (radius + 20);
-
- line.setLineWidth(20);
- line.setPosition(QPointF(x,y));
- angle += 25;
- }
-
- textLayout.endLayout();
- textLayout.draw(&painter, QPoint(0,0));
- }
QTextEdit 可以通过以下方式构造并用于显示HTML:
- QTextEdit *editor = new QTextEdit(parent);
- editor->setHtml(aStringContainingHTMLtext);
- editor->show();
默认 QTextEdit 包含一个带有根框架的文档,其中包含一个空文本块。可以获取此文档:
QTextDocument *document = editor->document();
QTextEdit 的光标也可用于编辑文档:
QTextCursor cursor = editor->textCursor();
虽然可以同时使用多个光标编辑文档,但 QTextEdit 一次只显示一个光标。因此,如果想更新编辑器以显示特定的光标或其选择,则需要在修改文档后设置编辑器的光标:
editor->setTextCursor(cursor);
要在文档中的两个点之间选择文本,需要将光标定位在第一个点,然后设置移动模式(QTextCursor::MoveMode)和移动操作(QTextCursor::MoveOperation)移动它。
选择文本时,选择的锚点保留在原来的光标位置:
- cursor.movePosition(QTextCursor::StartOfWord);
- cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
QTextDocument 提供了基于光标的搜索功能。
查找文档中所有的特定单词,并更改它们的颜色:
- auto document = ui->textEdit->document();
- auto searchString{"hello"};
-
- QTextCharFormat colorFormat;
- colorFormat.setBackground(Qt::cyan);
- QTextCursor newCursor(document);
- while (!newCursor.isNull() && !newCursor.atEnd())
- {
- newCursor = document->find(searchString, newCursor);
- if (!newCursor.isNull())
- {
- newCursor.movePosition(QTextCursor::NoMove,QTextCursor::KeepAnchor);
- newCursor.mergeCharFormat(colorFormat);
- }
- }
在每次搜索和替换操作后,不必移动光标,它总是位于搜索和被替换的词的末尾。
Qt富文本引擎支持的HTML标记:
a | 锚点或链接。更多。 |
address | 地址。更多。 |
b | 加粗。更多。 |
big | 比常规的字体大一号的字体。更多。 |
blockquote | 缩进段落。更多。 |
body | 文档的主体。更多。 |
br | 换行。更多。 |
center | 水平居中。更多。 |
cite | 表示它所包含的文本是对某个参考文献的引用。更多。 |
code | 表示它引用的文本是一段代码,怎么显示交给浏览器。更多。 |
dd | 不实用,略。 |
dfn | 不实用,略。 |
div | 一个块级元素,浏览器通常会在div元素前后放置一个换行符。div标签可以把文档分割为独立的、不同的部分。更多。 |
dl | 不实用,略。 |
dt | 不实用,略。 |
em | 突出显示文本。更多。 |
font | 字体,略。 |
h1~h6 | 1~6级的标题。h1是最大的。 |
head | 文档头部。更多。 |
hr | 显示为一条水平线。更多。 |
html | 是 HTML 文档中最外层的元素。更多。 |
i | 倾斜文本。更多。 |
img | 图片。更多。 |
kbd | 不实用,略。 |
meta | 提供了 HTML 文档的元数据。元数据不会显示在客户端,但是会被浏览器解析。更多。 |
li | 列表项,很实用。更多。 |
ol | 有序列表。更多。 |
ul | 无序列表。更多。 |
p | 标签定义段落。会自动在标签前后创建一些空白。更多。 |
pre | 内容所见即所得。更多。 |
s | 删除线。更多。 |
samp | 不实用,略。 |
small | 小字体。更多。 |
span | 被此元素包含的文本,可以使用独立的样式。更多。 |
strong | 粗体突出显示文本。 |
sub | 下标文本。更多。 |
sup | 上标文本。更多。 |
table | HTML 表格。更多。 |
tbody | 设置表格一部分的样式。更多。 |
td | 表格的单元格。更多。 |
tfoot | 页脚。更多。 |
th | 表头单元格。更多。 |
thead | 表头。更多。 |
title | 略。 |
tr | 表格中的行。更多。 |
u | 文本下划线。 |
使用css属性示例:
- ui->textEdit->setHtml(R"(
-
- body
- {
- text-align:center;
- background-color:green;
- }
- h1
- {
- color:white;
- background-color:blue;
- }
- h2
- {
- color:white;
- background-color:black;
- }
-
-
我是h1
-
我是h2
- )");
Qt富文本引擎支持的CSS属性:
background-color | 背景色。更多。 |
background-image | 背景图片。更多。 |
background | 所有背景属性。更多。 |
color | 文字颜色。更多。 |
font-family | 字体族。更多。 |
font-style | 字体样式。更多。 |
font-weight | 字体粗细。更多。 |
font | 字体所有属性。更多。 |
text-decoration | 文本装饰,下划线、上划线、删除线等。更多。 |
text-indent | 文本块中首行文本的缩进。更多。 |
white-space | 空白的处理方式。更多。 |
margin-top | 元素的四个边距。更多。 |
padding-top padding-bottom padding-left padding-right padding | 元素填充边距。更多。 |
vertical-align | 垂直对齐方式。更多。 |
border-collapse | 表格的边框是被合并为一个单一的边框,还是像在标准的 HTML 中那样分开显示。更多。 |
border-color border-top-color border-bottom-color border-left-color border-right-color | 边框颜色。更多。 |
border-style border-top-style border-bottom-style border-left-style border-right-style | 边框样式。更多。 |
border-width border-top-width border-bottom-width border-left-width border-right-width | 边框宽度。更多。 |
border border-left border-right border-top border-bottom | 所有边框属性。更多。 |
float | 指定一个元素的浮动方式。更多。 |
text-transform | 文本大小写。更多。 |
font-variant | |
line-height | 以百分比计数的行高。更多。 |
可以使用以下Qt特定属性来设置文本块的样式:
测试发现设置为1会缩进半个制表符的空间。