Qt 富文本处理

摘要:
所有富文本处理类都围绕QTextDocument展开,这确保用户可以创建和修改富文本块,而无需定义中间语言。RichTextDocumentStructureQTextDocument是文档的抽象。它包括文档的内部结构,可以通过跟踪更改提供撤消/重做操作。Qt通过blockframetable和其他类的树结构表示文档。它们是块级和文档级。QAbstractTextDocumentLayout是一个抽象类,用于管理文档中的所有文本布局。富格文本处理概述常规文本操作包括使用QTextEdit和QTextBrowser编辑文档、使用QTextDocument创建文档、使用QextCursor编辑文档以及打印。QTextBrowser提供超链接文本的显示。
富文本处理

所有的类围绕 QTextDocument 展开, 它保证了用户可以创建和修改 富文本块, 而无须定义中间语言。
一个 QTextDocument 可以通过两个接口操作, 一个是用于编辑的 Cusor based 接口, 一个是只读的文档结构树。

Rich Text Document Structure

QTextDocument 是一个文档的抽象, 它包括了文档的内部结构, 并且能够通过跟踪变化以提供 undo / redo 操作。 Qt通过 block frame table 以及其他类的树状结构表示文档。 Frame 和 table 用于组织其它结构, 而 block 包含实际内容。

QDocument 可以从 QTextEdit 中获取, 也可以是用默认构造。 这样可以保证 控件和 document的轻耦合。 一个空的文档包括了一个 root frame , 它包括了一个空的block 。 table 是 frame 的一个 子类, 它的行和列都可以单独包含 block。 富文本结构

  • Block 包含 fragment, 每一个fragment 都包含了 文字 和 字符的格式信息。文字格式信息包含于 block 和 character 两个层面。
  • Character 包含了字体、文字颜色、字体加粗等信息, block 包含了 文字方向、排版以及背景色等信息。
  • Image 使用 fragment 表示。

QTextObject 的子类可以归并文档元素: QTextBlockGroup 可以归并 block; QTextFrame 可以归并 block 以及其它 元素。

一个frame 结构可以包括 多个 或者0个 frame,至少1个block; 它的 format 决定了frame在 页面上如何被渲染和定位。使用 iterator 可以遍历frame 结构,但是要注意 iterator 的数据类型是不确定的。

QTextList 是 QTextBlockGroup 的一个子类, 它并不是 把 list item 当作它的子元素, 而是提供了一系列用于操作list item的函数。 可以如下使用

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);
        }
    }
}

The QTextCursor Interface

Cursor 可以通过一个构造函数创建, 也可以在 edit widget 中获取。

cursor 可以以 block 为单位, 保存选区信息。

一个 document 里面可以有多个 cursor, 但是只有一个是可见的; paste 和 copy操作就是这样实现的。 通过简单的继承, 可以实现很多复杂的操作。

Cursor 能够追踪它在 document 中的位置, 以及所在结构。

cursor一系列的 edit可以被打包, 这样能够在 redo 和 undo 中把它作为一个操作看待。一般使用 beginEditBlock 开始, endEditBlock 结束。

Cursor 的insert 有两个级别。 分别是 block 级别, 和 document级别。 Block级别可以插入 block 、 fragment 、 image 、text等; document 级别 插入 frame 、 table、 list, 这个级别的插入会在当前 frame 内、 当前block 以后。

可以在当前块中插入 当前文字格式 的字符串, 也可以插入自定义字符格式的字符串; 一旦在使用cursor 插入时使用了一个格式,那么这个格式会成为以后的 cursor 插入的默认格式,除非使用一个新的格式(替代了它)。

cursor.insertText(tr("Character formats"),headingFormat);
cursor.insertBlock();
cursor.insertText(tr("Text can be displayed in a variety of "
                              "different character formats. "), plainFormat);
cursor.insertText(tr("We can emphasize text by "));
cursor.insertText(tr("making it italic"), emphasisFormat);

Document Layouts
Document Layout 仅仅在文档的展示、需要展示的变化发生时有意义。

QAbstractTextDocumentLayout 是文档中管理所有 text layout 的抽象类。

富文本处理过程概述

常规的文本操作包括, 使用 QTextEdit 和 QTextBrowser 编辑文档, 使用QTextDocument 创建文档, 使用 QTextCursor 编辑文档, 以及打印等。

QTextBrowser 提供对有超链接文本的展示。 如果在文末使用 #anchor, 在文本滚动显示时会自动加载 anchor 所指内容。

QTextDocument 的查找是基于 QCursor 的。 如下:

QTextCursor newCursor(document);
while (!newCursor.isNull() &&!newCursor.atEnd()) {
    newCursor = document->find(searchString, newCursor);
    if (!newCursor.isNull()) {
        newCursor.movePosition(QTextCursor::WordRight,
                               QTextCursor::KeepAnchor);
        newCursor.mergeCharFormat(colorFormat);
    }
}

Printing
QTextEdit 用于展示大文件在屏幕上可读的部分, 使用和 web 浏览器相同的方法去渲染。 它没有分页的功能。

QTextDocument 提供了 print 函数, 以下代码展示了如何使用 QPrinter 打印。

QTextDocument*document = editor->document();
QPrinter printer;
QPrintDialog*dlg =newQPrintDialog(&printer,this);
if (dlg->exec() !=QDialog::Accepted)
    return;
document->print(&printer);

Advanced Rich Text Processing
Qt 在处理文字时没有对文件大小做出限制,因此这有可能导致你的应用在加载文件时失去响应。 也有一些其它问题也会导致程序的性能降低。 因此有以下几个规则。

把大的段落分割成较小的段落。

把 文件中 block 的数目限制在 maximumBlockCount() 以内。

以块为单位把文档加载到 text edit, 如下。 因为很多时候text edit 都没有必要加载一整个文档。

textEdit.show();
textCursor.beginEditBlock();
for (int i =0; i <1000; ++i) {
    textCursor.insertBlock();
    textCursor.insertText(paragraphText.at(i));
}
textCursor.endEditBlock();

Supported HTML Subset

Qt 的 text widgets支持html4的语法子集, 具体可以参考 Qt Mannual - Supported HTML Subset 。

免责声明:文章转载自《Qt 富文本处理》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇批处理--md5校检mysql db [Warning] IP address 'xxxx' could not be resolved: Name or service not known下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

PS如何把印章颜色加重更加清晰?

我的问题是加深这个印章上的红色,然后看起来更清晰,而不会影响最下面一行文字的颜色。步骤1:打开PS软件并创建新文档。白边的实际密封尺寸设置为5cm,分辨率设置为72像素/英寸。在本例中,图像更清晰;步骤2:在工具栏中选择椭圆工具。注意图中的红色圆圈2。确保选择图形层而不是路径。...

virsh 连接虚拟机 (vnc 或 控制台)

第一种方法:1.如果虚拟机登录方法是VNC,请在ubuntu机器上安装vncviewer。在虚拟机的配置xml中,安装vncviewer$apt-geinstallvncviewer以查看虚拟机的端口地址$virshvncdisplaycontroller通过端口地址显示:0...

springsession生成sessionid不一致问题解决

毫无疑问,我遇到的主要问题是两个不同版本的spring boot,需要共享sessionid。...

antd中,popover 不同情境下设置不同背景图,无法设置className的情况

于是就想通过设置不同的status值来添加不同的className,以设置.ant-popover-inner的样式来设置背景图,当然,这样做有一个不完美的就是不能一步到位的全部改变,需要手动更改.ant-popover-placement-bottom˃.ant-popover-content˃.ant-popover-arrow来替换那个角角的值。问题就...

AVUE 下拉 select 获取选中项的文本

底层应该不支持,其它方式应该可以,到时候看看黎大神给的方案。...

每个文件之间延迟启动批处理bat方法之一

延迟在文件之间启动批处理的方法之一:。文本→. bat将扩展名更改为.bat或在txt中将其另存为.bat。例如,如果B是包含空格的路径名,请使用引号“”,否则将找不到文件。批处理bat要运行的文件位于同一目录文件夹@echoffstart xiongmaoshu.jpgping127.0.0.1-n 10&gt;批处理bat和文件是否位于同一目录文...