富文本處理
富文本(Rich Text)或者叫做富文本格式,簡單來說就是在文檔中可以使用多種格式,比如字體顏色、圖片和表格等等。它是與純文本(Plain Text)相對而言的,比如Windows上的記事本就是純文本編輯器,而Word就是富文本編輯器。
- 富文本文檔結構
- 文本塊
- 表格、列表與圖片
- 查找功能
- 語法高亮與HTML
1 富文本文檔結構
在Qt中提供了對富文本處理的支持。Qt中對富文本的處理分為了編輯操作和只讀操作兩種方式。
- 編輯操作是使用基於光標的一些接口函數,這樣更好的模擬了用戶的編輯操作,更加容易理解,而且不會丟失底層的文檔框架。
- 而對於文檔結構的概覽,使用了只讀的分層次的接口函數,它們有利於文檔的檢索和輸出。
對於文檔的讀取和編輯要使用不同方面的兩組接口。
- 文檔的光標主要基於QTextCursor類
- 文檔的框架主要基於QTextDocument類
一個富文本文檔的結構被分為了幾種元素來表示:
- 框架(QTextFrame)
- 文本塊(QTextBlock)
- 表格(QTextTable)
- 列表(QTextList)
每種元素的格式又使用相應的format類來表示:
- 框架格式(QTextFrameFormat)
- 文本塊格式(QTextBlockFormat)
- 表格格式(QTextTableFormat)
- 列表格式(QTextListFormat)
這些格式一般在編輯文檔時使用,所以它們常和QTextCursor類配合使用。
因為QTextEdit類就是一個富文本編輯器,所以在構建QTextEdit類的對象時就已經構建了一個QTextDocument類對象和一個QTextCursor類對象,只需調用它們進行相應的操作即可。
一個空的文檔包含了一個根框架(Root frame),這個根框架又包含了一個空的文本塊(Block)。框架將一個文檔分為多個部分,在根框架里可以再添加文本塊、子框架和表格等。
設置根框架
1 QTextDocument *document = ui->textEdit->document(); //獲取文檔對象 2 3 QTextFrame *rootFrame = document->rootFrame(); // 獲取根框架 4 5 QTextFrameFormat format; // 創建框架格式 6 7 format.setBorderBrush(Qt::red); // 邊界顏色 8 9 format.setBorder(3); // 邊界寬度 10 11 rootFrame->setFrameFormat(format); // 框架使用格式
添加子框架
1 QTextFrameFormat frameFormat; 2 3 frameFormat.setBackground(Qt::lightGray); // 設置背景顏色 4 5 frameFormat.setMargin(10); // 設置邊距 6 7 frameFormat.setPadding(5); // 設置填襯 8 9 frameFormat.setBorder(2); 10 11 //設置邊框樣式 12 frameFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Dotted); 13 14 QTextCursor cursor = ui->textEdit->textCursor(); // 獲取光標 15 16 cursor.insertFrame(frameFormat); // 在光標處插入框架
2 文本塊
文本塊QTextBlock類為文本文檔QTextDocument提供了一個文本片段(QTextFragment)的容器。
一個文本塊可以看做是一個段落,但是它不能使用回車換行,因為一個回車換行就表示創建一個新的文本塊。QTextBlock提供了只讀接口,它是前面提到的文檔分層次的接口的一部分,如果QTextFrame看做是一層,那么其中的QTextBlock就是另一層。
文本塊的格式由QTextBlockFormat類來處理,它主要涉及對齊方式,文本塊四周的邊白,縮進等內容。而文本塊中的文本內容的格式,比如字體大小、加粗、下划線等內容,則由QTextCharFormat類來設置。
遍歷框架
1 QTextDocument *document = ui->textEdit->document(); 2 QTextFrame *frame = document->rootFrame(); 3 QTextFrame::iterator it; // 建立QTextFrame類的迭代器 4 for (it = frame->begin(); !(it.atEnd()); ++it) { 5 QTextFrame *childFrame = it.currentFrame();// 獲取當前框架的指針 6 QTextBlock childBlock = it.currentBlock(); // 獲取當前文本塊 7 if (childFrame) 8 qDebug() << "frame"; 9 else if (childBlock.isValid()) 10 qDebug() << "block:" << childBlock.text(); 11 }
遍歷子框架
1 QTextDocument *document = ui->textEdit->document(); 2 QTextBlock block = document->firstBlock(); // 獲取文檔的第一個文本塊 3 for (int i = 0; i < document->blockCount(); i++) { 4 qDebug() << tr("文本塊%1,文本塊首行行號為:%2,長度為:%3,內容為:") 5 .arg(i).arg(block.firstLineNumber()).arg(block.length()) 6 << block.text(); 7 block = block.next(); // 獲取下一個文本塊 8 }
1 QTextCursor cursor = ui->textEdit->textCursor(); 2 QTextBlockFormat blockFormat; // 文本塊格式 3 blockFormat.setAlignment(Qt::AlignCenter); // 水平居中 4 cursor.insertBlock(blockFormat); // 使用文本塊格式 5 QTextCharFormat charFormat;// 字符格式 6 charFormat.setBackground(Qt::lightGray); // 背景色 7 charFormat.setForeground(Qt::blue);// 字體顏色 8 // 使用宋體,12號,加粗,傾斜 9 charFormat.setFont(QFont(tr("宋體"), 12, QFont::Bold, true)); 10 charFormat.setFontUnderline(true); // 使用下划線 11 cursor.setCharFormat(charFormat); // 使用字符格式 12 cursor.insertText(tr("測試字體")); // 插入文本
3 表格、列表和圖片
1 //插入表格 2 QTextCursor cursor = ui->textEdit->textCursor(); 3 QTextTableFormat format; // 表格格式 4 format.setCellSpacing(2); // 表格外邊白 5 format.setCellPadding(10); // 表格內邊白 6 cursor.insertTable(2, 2, format); // 插入2行2列表格 7 //插入列表 8 QTextListFormat format; // 列表格式 9 format.setStyle(QTextListFormat::ListDecimal); // 數字編號 10 ui->textEdit->textCursor().insertList(format); 11 //插入圖片 12 QTextImageFormat format; // 圖片格式 13 format.setName("logo.png"); // 圖片路徑 14 ui->textEdit->textCursor().insertImage(format);
4 查找功能
1 //查找文本 2 QDialog *dlg = new QDialog(this); // 創建對話框 3 lineEdit = new QLineEdit(dlg); // 創建行編輯器 4 QPushButton *btn = new QPushButton(dlg); // 創建按鈕 5 btn->setText(tr("查找下一個")); 6 connect(btn,SIGNAL(clicked()),this,SLOT(findNext())); // 關聯信號和槽 7 QVBoxLayout *layout = new QVBoxLayout; // 創建垂直布局管理器 8 layout->addWidget(lineEdit); // 添加部件 9 layout->addWidget(btn); 10 dlg->setLayout(layout); // 在對話框中使用布局管理器 11 dlg->show(); 12 13 //查找下一個 14 QString string = lineEdit->text(); 15 // 使用查找函數查找指定字符串,查找方式為向后查找 16 bool isfind = ui->textEdit->find(string, QTextDocument::FindBackward); 17 if(isfind){ // 如果查找成功,輸出字符串所在行和列的編號 18 qDebug() << tr("行號:%1 列號:%2") 19 .arg(ui->textEdit->textCursor().blockNumber()) 20 .arg(ui->textEdit->textCursor().columnNumber()); 21 }
5 語法高亮
在使用Qt Creator編輯代碼時可以發現,輸入關鍵字時會顯示不同的顏色,這就是所謂的語法高亮。
在Qt的富文本處理中提供了QSyntaxHighlighter類來實現語法高亮。為了實現這個功能,需要創建QSyntaxHighlighter類的子類,然后重新實現highlightBlock()函數,使用時直接將QTextDocument類對象指針作為其父部件指針,這樣就可以自動調用highlightBlock()函數了。
例如,自定義的類為MySyntaxHighlighter,像這樣來使用: highlighter = new MySyntaxHighlighter(ui->textEdit->document()); 這里創建了MySyntaxHighlighter類的對象,並且使用編輯器的文檔對象指針作為其參數,這樣,每當編輯器中的文本改變時都會調用highlightBlock()函數來設置語法高亮。
重新實現highlightBlock()函數:
1 QTextCharFormat myFormat; // 字符格式 2 myFormat.setFontWeight(QFont::Bold); 3 myFormat.setForeground(Qt::green); 4 QString pattern = "\\bchar\\b"; // 要匹配的字符,這里是“char”單詞 5 QRegExp expression(pattern); // 創建正則表達式 6 int index = text.indexOf(expression); // 從位置0開始匹配字符串 7 // 如果匹配成功,那么返回值為字符串的起始位置,它大於或等於0 8 while (index >= 0) { 9 int length = expression.matchedLength(); // 要匹配字符串的長度 10 setFormat(index, length, myFormat); // 對要匹配的字符串設置格式 11 index = text.indexOf(expression, index + length); // 繼續匹配 12 } 13 在這里主要是使用了正則表達式和QString類的indexOf()函數來進行字
在這里主要是使用了正則表達式和QString類的indexOf()函數來進行字符串的匹配,如果匹配成功,則使用QSyntaxHighlighter類的setFormat()函數來設置字符格式。
6 HTML
在富文本處理中還提供了對HTML子集的支持,可以在QLabel或者QTextEdit添加文本時使用HTML標簽或者CSS屬性,例如:
ui->textEdit->append(tr("<h1><font color=red>使用HTML</font></h1>"));
這里往編輯器中添加了文本,並且使用了HTML標簽,
本文鏈接:https://blog.csdn.net/qq_40732350/article/details/86696217