参考《Qt Creator快速入门(第三版)》。
富文本Rich Text,简单说就是在文档中可以使用多种格式,比如字体颜色、图片和表格等,是与纯文本相对而言的。比如Windows上的记事本就是纯文本编辑器,word是富文本编辑器。
Qt对富文本的处理分为编辑操作和只读操作两种方式。
所以对于文档的读取和编辑要使用不同的两组接口。文档的光标主要基于QTextCursor类,文档的框架主要基于QTextDocument类。
一个富文本文档的结构分为几种元素来表示,分别是:框架、文本块、表格、列表,每种元素的格式又使用相应的format类来表示。
一个空的文档包含了一个根框架,这个根框架又包含一个空的文本块,在根框架中又可以再添加文本块、子框架、表格等。
框架属性示意图:
获取编辑器的文档对象,获取文档的根框架并重新设置框架的格式,示例代码:
// 获取文档对象
QTextDocument *textDocument = ui->textEdit->document();
// 获取根框架
QTextFrame *rootFrame = textDocument->rootFrame();
// 创建框架格式
QTextFrameFormat textFrameFormat;
// 设置框架的边界颜色
textFrameFormat.setBorderBrush(Qt::red);
// 设置框架的边界宽度
textFrameFormat.setBorder(2);
// 设置根框架使用框架格式
rootFrame->setFrameFormat(textFrameFormat);
在根框架中再添加一个子框架,示例代码:
// 在根框架中再添加一个子框架
QTextFrameFormat frameFormat; // 框架格式
// 设置背景颜色
frameFormat.setBackground(Qt::lightGray);
// 设置边距
frameFormat.setMargin(10);
// 设置填衬
frameFormat.setPadding(5);
// 设置边界宽度
frameFormat.setBorder(3);
// 设置边框样式
frameFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Dotted);
// 获取光标
QTextCursor cursor = ui->textEdit->textCursor();
// 在光标处插入框架
cursor.insertFrame(frameFormat);
文本块类QTextBlock为文本文档提供一个文本片段的容器。一个回车换行表示创建一个新的文本块,一个文本块可以看作一个段落。
QTextBlock提供了只读接口。
文本块的格式由QTextBlockFormat类来处理,主要涉及对齐方式、文本块四周边距、缩进等内容。
文本块中的文本内容的格式由QTextCharFormat类处理,比如字体大小、加粗、下划线等。
实现遍历文档中的框架示例代码:
void MainWindow::showTextFrame() // 遍历框架
{
// 获取文档
QTextDocument *document = ui->textEdit->document();
// 获取根框架
QTextFrame *frame = document->rootFrame();
// 建立QTextFrame类的迭代器
QTextFrame::iterator it;
for(it = frame->begin();it != frame->end();++it)
{
// 获取当前框架的指针, currentFrame()如果获取到的是文本块则返回0
QTextFrame *childFrame = it.currentFrame();
// 获取当前文本块,currentBlock()如果获取到的是框架,则返回的块无效,可以用isValid()判断返回的块是否OK
QTextBlock childBlock = it.currentBlock();
if(childFrame)
qDebug() << tr("frame");
if(childBlock.isValid())
qDebug() << tr("block:") << childBlock.text();
}
}
遍历所有文本块示例代码:
void MainWindow::showTextBlock()
{
// 遍历文本块
// 获取文档
QTextDocument * document = ui->textEdit->document();
QTextBlock block = document->firstBlock(); // 获取文档的第一个文本块
for(int i=0;i<document->blockCount();++i) // blockCount()获取文档中所有文本块的个数
{
qDebug() << tr("文本块 %1,文本块首行行号为:%2,长度为:%3,内容为:%4")
.arg(i)
.arg(block.firstLineNumber())
.arg(block.length())
.arg(block.text());
block = block.next(); // 获取下一个文本块
}
}
编辑操作,设置文本块格式,文本块中的文本内容格式、并插入文本进行测试,示例代码:
void MainWindow::setTextFont(bool checked)
{
// 设置字体格式
if(checked) // 如果处于选中状态
{
// 获取文本块的光标
QTextCursor cursor = ui->textEdit->textCursor();
// 设置文本块格式
QTextBlockFormat blockFrame;
blockFrame.setAlignment(Qt::AlignCenter); // 设置水平剧中
cursor.insertBlock(blockFrame); // 使用文本块格式
QTextCharFormat charFormat; // 设置字符格式
charFormat.setBackground(Qt::darkGray); // 设置背景色
charFormat.setForeground(Qt::blue); // 设置字体颜色
charFormat.setFont(QFont(tr("宋体"),12,QFont::Bold,true)); // 设置字体为宋体,字号12,粗体 斜体
charFormat.setFontUnderline(true); // 设置使用下划线
cursor.setCharFormat(charFormat); // 设置使用字符格式
cursor.insertText(tr("测试字体")); // 插入文本
}
else
{
qDebug() << tr("未选择字体,执行其它操作");
}
}
表格和列表也可以使用QTextFrame::iterator来遍历它们。
表格对应的是QTextTable类,该类提供了一些常用函数:
表格中的单元格对应的类是QTextTableCell,对应的格式类是QTextTableCellFormat类。
列表对应的类是QTextList,该类提供了一些常用函数:
图片使用QTextImageFormat类,可以使用QTextImageFormat::setHeight()和QTextImageFormat::setWidth()设置图片的高度和宽度,可以使用QTextImageFormat::setName()指定图片。
示例代码:
void MainWindow::insertTable()
{
// 插入表格
QTextCursor cursor = ui->textEdit->textCursor();
QTextTableFormat format;
format.setCellSpacing(2); // 设置表格的单元格间距,相邻单元格之间的距离
format.setCellPadding(10); // 设置单元格边框与内容之间的距离
cursor.insertTable(2,2,format); // 在当前光标处插入2行2列的表格
}
void MainWindow::insertList() // 插入列表
{
QTextListFormat format;
format.setStyle(QTextListFormat::ListLowerAlpha); // 设置列表格式为数字编号
ui->textEdit->textCursor().insertList(format);
}
void MainWindow::insertImage() // 插入图片
{
QTextImageFormat format;
format.setName(":/images/BackButton.png"); // 设置图片路径
ui->textEdit->textCursor().insertImage(format);
}
类似字体设置等的操作可以在QTextEdit等富文本编辑类中直接进行,QTextEdit提供了很多方便的函数,比如常用的复制、粘贴、撤销、恢复、放大、缩小等操作。
这里介绍文本查找功能,使用的是QTextEdit::find()函数。
更多的查找功能可以使用QTextDocument类的find函数,还可以使用正则表达式。
QTextEdit::find()查找字符示例代码:
void MainWindow::findNext() // 查找下一个
{
QString str = lineEdit->text(); // 获取要查找的字符串
// 使用查找函数查找指定字符串,查找方式为向后查找
bool isFind = ui->textEdit->find(str,QTextDocument::FindBackward);
if(isFind) // 如果找到
{
qDebug() << tr("行号:%1 列号:%2")
.arg(ui->textEdit->textCursor().blockNumber())
.arg(ui->textEdit->textCursor().columnNumber());
}
else{
qDebug() << tr("没有找到,从头开始查找");
ui->textEdit->textCursor().setPosition(1,QTextCursor::MoveAnchor);
}
}
Qt的富文本处理中类QSyntaxHighlighter实现语法高亮。要实现这个功能,需要创建QSyntaxHighlighter类的子类,然后重新实现highlightBlock()函数,使用时直接将QTextDocument类对象指针作为其父部件指针,这样的话就可以自动调用highlightBlock()函数了。
首先新建QSyntaxHighlighter的子类,设置构造函数传入的父类为QTextDocument指针对象,并在子类中重写highlightBlock()函数。
void MySyntaxHighlighter::highlightBlock(const QString &text)
{
// 重新实现文本块高亮函数
QTextCharFormat myFormat;
myFormat.setFontWeight(QFont::Bold); // 将文本的字体设置为粗体
myFormat.setForeground(Qt::green); // 将文本内容颜色设置为绿色
QString pattern = "\\bchar\\b"; // 要匹配的字符,这里匹配 char 单词
QRegExp expression(pattern);
int index = text.indexOf(expression); // 从位置0开始匹配字符串,匹配成功返回字符串的起始位置
while (index >= 0) {
int length = expression.matchedLength(); // 要匹配的字符串的长度
setFormat(index,length,myFormat); // 对要匹配的字符串设置格式
index = text.indexOf(expression,index+length); // 继续匹配
}
}
在调用函数中,创建MySyntaxHighlighter类对象,并传入QTextEdit的文档对象。此时在编辑器中输入char就会高亮显示。