Qt開發技術:Qt富文本(一)富文本介紹、文檔結構

若該文爲原創文章,未經允許不得轉載
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客導航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/105594953
各位讀者,知識無窮而人力有窮,要麼改需求,要麼找專業人士,要麼自己研究

目錄

前話

富文本處理

概述

富文本文檔結構

文本光標接口

文檔佈局

常見的富文本編輯任務

高級富文本

支持的HTML子集

富文本文檔結構

概述

基本結構

富文本文檔

文檔元素

文本塊:QTextBlock

文本框架:QTextFrame

表格:QTextTable

列表:QTextList

圖像:QTextFragment


Qt開發專欄:開發技術(傳送門)

Qt開發技術:Qt富文本(一)富文本介紹、文檔結構

《Qt開發技術:Qt富文本(二)Qt文本光標操作、文檔佈局、富文本編輯和處理以及Demo》

《Qt開發技術:Qt富文本(三)Qt支持的HTML子集(查詢手冊)以及涉及的類》

 

    Qt開發技術:Qt富文本(一)富文本介紹、文檔結構

 

前話

      紅胖子,來也!

      Qt的富文本技術介紹,富文本的文檔結構。

 

富文本處理

概述

Scribe框架提供了一組用於讀取和操作結構化富文本文檔的類。與Qt中以前的富文本支持不同,新類以QTextDocument類爲中心,而不是以原始文本信息爲中心。這使開發人員能夠創建和修改結構化富文本文檔,而無需準備中間標記格式的內容。

文檔中的信息可以通過兩個相互補充的接口訪問:

  • 基於光標的接口用於編輯:可以使用模擬用戶與編輯器交互的操作編輯文本,而不會丟失文檔的底層結構。
  • 只讀層次接口提供文檔結構的高級描述:在執行搜索和文檔導出等操作時,只讀分層界面最有用。

富文本文檔結構

概述了QTextDocument中的各種元素,並描述了它們在文檔結構中的排列方式。

文本光標接口

QTextCursor接口解釋瞭如何使用基於光標(光標)的接口編輯富文本文檔。

文檔佈局

簡要說明文檔佈局的作用。

常見的富文本編輯任務

檢查一些涉及閱讀或操作富文本文檔的常見任務。

高級富文本

高級富文本處理檢查高級富文本編輯任務。

支持的HTML子集

列出QTextDocument支持的HTML標記。

 

富文本文檔結構

概述

文本文檔由QTextDocument類表示,該類包含有關文檔的內部表示、其結構的信息,並跟蹤修改以提供撤消/重做功能。

文本文檔的結構化表示將其內容表示爲文本塊、框架、表和其他對象的層次結構。它們爲文檔提供了邏輯結構,並描述了它們的內容將如何顯示。通常,框架和表用於將其他結構分組,而文本塊包含實際的文本信息。

使用QTextCursor或使用編輯器小部件(如QTextEdit)以編程方式創建新元素並將其插入到文檔中。創建元素時,可以爲其指定特定格式;否則,它們將採用元素的光標當前格式。

基本結構

文檔的“頂層”可能按所示的方式填充。每個文檔總是包含一個根框架,並且它總是至少包含一個文本塊。

對於具有某些文本內容的文檔,根框架通常包含一系列塊和其他元素

即使文本塊不包含任何信息,文檔中的框架和表序列始終由文本塊分隔。這樣可以確保新元素始終可以插入現有結構之間。

富文本文檔

QTextDocument對象包含構造富文本文檔所需的所有信息。文本文檔可以通過兩種互補的方式訪問:作爲編輯器使用的線性緩衝區,以及作爲對佈局引擎有用的對象層次結構。在分層文檔模型中,對象通常對應於可視元素,如框架、表和列表。在較低的級別上,這些元素描述文本樣式和對齊方式等屬性。文檔的線性表示用於編輯和操作文檔內容。

儘管QTextEdit使顯示和編輯富文本變得容易,但文檔也可以獨立於任何編輯器小部件使用,例如:

QTextDocument *pTextDocument = new QTextDocument;

或者,可以從現有編輯器中提取它們:

QTextEdit *pTextEdit = new QTextEdit;
QTextDocument *pTextDocument = pTextEdit->document();

這種靈活性使應用程序能夠處理多個富文本文檔,而無需多個編輯器小部件的開銷,或要求文檔以某種中間格式存儲。

空文檔包含根框架,根框架本身包含單個空文本塊。框架提供了文檔各部分之間的邏輯分隔,但也具有確定它們在呈現時的顯示方式的屬性。表格是一種特殊的框架類型,它由多個單元格組成,按行和列排列,每個單元格都可以包含進一步的結構和文本。表提供了管理和佈局功能,允許創建靈活的單元格配置。

文本塊包含文本片段,每個片段指定文本和字符格式信息。文本屬性是在字符級和塊級定義的。在字符級別,可以指定字體系列、文本顏色和字體粗細等屬性。塊級特性控制文本的高級外觀和行爲,例如文本流的方向、對齊方式和背景顏色。

文檔結構不是直接操作的。通過基於光標的界面執行編輯。文本光標界面自動將新的文檔元素插入到根框架中,並確保在必要時用空塊填充。

通過以下方式獲得根框架:

QTextDocument *textDocument;
QTextFrame *root = textDocument->rootFrame();

在導航文檔結構時,從根框架開始很有用,因爲它提供了對整個文檔結構的訪問。

文檔元素

富文本文檔通常由常見元素組成,如段落、框架、表和列表。這些在QTextDocument中由QTextBlock、QTextFrame、QTextTable和QTextList類表示。與文檔中的其他元素不同,圖像由特殊格式的文本片段表示。這使它們能夠與周圍的文本以內聯格式放置。

文檔中的基本構造塊是QTextBlock和QTextFrame。塊本身包含富文本片段(QTextFragment),但這些片段不會直接影響文檔的高級結構。

可以將其他文檔元素組合在一起的元素通常是QTextObject的子類,分爲兩類:

  • 將文本塊組合在一起的元素是QTextBlockGroup的子類;
  • 將框架和其他元素組合在一起的元素是QTextFrame的子類。

文本塊:QTextBlock

      文本塊由QTextBlock類提供。

文本塊將不同字符格式的文本片段組合在一起,用於表示文檔中的段落。每個塊通常包含許多具有不同樣式的文本片段。在將文本插入文檔時創建片段,而在編輯文檔時添加更多片段。

文檔將拆分、合併和移除片段,以便有效地表示塊中不同樣式的文本。

通過使用QTextBlock::iterator迭代器遍歷塊的內部結構,可以檢查給定塊中的片段:

QTextBlock::iterator it;
for (it = currentBlock.begin(); !(it.atEnd()); ++it) 
{
    QTextFragment currentFragment = it.fragment();
    if (currentFragment.isValid()) 
    {
        processFragment(currentFragment);  // processFragment處理片段
    }
}

文本塊還用於表示列表項。因此,塊可以定義自己的字符格式,其中包含有關塊級描述的信息,例如用於列表項的項目符號類型。

文本塊本身的格式由QTextBlockFormat類描述,並描述文本對齊、縮進和背景色等屬性。

儘管給定的文檔可能包含複雜的結構,但一旦我們引用了文檔中的有效塊,我們就可以按照它們的寫入順序在每個文本塊之間導航:

QTextBlock currentBlock = textDocument->begin();
while (currentBlock.isValid())
{
    processBlock(currentBlock);  // processBlock處理塊
    currentBlock = currentBlock.next();
}

當只想從文檔中提取富文本時,此方法非常有用,因爲它忽略框架、表和其他類型的結構。

QTextBlock提供比較運算符,使操作塊更容易:operator==()operator!=()用於測試兩個塊是否相同,而運算符operator<()用於確定文檔中哪個塊最先出現。

文本框架:QTextFrame

文本框架由QTextFrame類提供。

文本框架將文本塊和子框架組合在一起,創建大於段落的文檔結構。框架的格式指定如何在頁面上呈現和定位它。框架要麼插入到文本流中,要麼浮在頁面的左側或右側。每個文檔都包含一個根框架,其中包含所有其他文檔元素。因此,除了根文本框架之外的所有文本框架都有父文本框架。

由於文本塊用於分隔其他文檔元素,因此每個框架將始終至少包含一個文本塊和零個或多個子框架。我們可以使用QTextFrame::iterator遍歷文本框架的子元素來檢查文本框架的內容:

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類都可以互補地用於從文檔中提取所需的結構。

表格:QTextTable

表由QTextTable類提供。

表是按行和列排列的單元格集合。每個表單元格都是具有自己字符格式的文檔元素,但也可以包含其他元素,如框架和文本塊。在構造表或添加額外的行或列時,將自動創建表單元格。它們也可以在桌子之間移動。

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

列表:QTextList

列表由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);
        }
    }
}

圖像:QTextFragment

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

通過遍歷包含圖像的文本塊中的片段,可以找到表示圖像的片段。

 

原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客導航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/105594953

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章