1. 程式人生 > >Qt中富文字處理相關類

Qt中富文字處理相關類

1、QAbstractTextDocumentLayout:抽象基類,用於實現QTextDocuments的自定義佈局。Qt提供的標準佈局可以處理簡單的字處理,包括內聯影象、列表和表。有些應用程式,例如文書處理程式或DTP應用程式可能需要比Qt佈局引擎提供的功能更多的特性,在這種情況下,您可以子類化QAbstractTextDocumentLayout以為文字文件提供定製佈局行為。

2、QFont:指定用於繪製文字的字型。用於設定字型、大小、格式等

3、QSyntaxHighlighter:允許您定義語法高亮顯示規則,此外,您還可以使用該類查詢文件的當前格式或使用者資料

class Highlighter : public QSyntaxHighlighter
{
    Q_OBJECT
public:
    Highlighter(QTextDocument *parent = 0);
protected:
    /*
     * 要提供自己的語法高亮顯示,必須子類化QSyntaxHighlighter並重新實現highlightBlock()。
     * 在重新實現時,應該解析塊的文字,並根據需要經常呼叫setFormat()來應用所需的任何字型和顏色更改。
     */
    void highlightBlock(const QString &text) override;

private:
    struct HighlightingRule
    {
        QRegularExpression pattern;
        QTextCharFormat format;
    };
    QVector<HighlightingRule> highlightingRules;//存放高亮的各種規則

    //使用正則表示式匹配
    QRegularExpression commentStartExpression;
    QRegularExpression commentEndExpression;

    //字元的格式
    QTextCharFormat keywordFormat;
    QTextCharFormat classFormat;
    QTextCharFormat singleLineCommentFormat;
    QTextCharFormat multiLineCommentFormat;
    QTextCharFormat quotationFormat;
    QTextCharFormat functionFormat;
};
Highlighter::Highlighter(QTextDocument *parent)
    :QSyntaxHighlighter(parent)
{
    HighlightingRule rule;
    keywordFormat.setForeground(Qt::darkBlue);
    keywordFormat.setFontWeight(QFont::Bold);
    QStringList keywordPatterns;
    keywordPatterns << "\\bchar\\b" << "\\bclass\\b"
                    << "\\bconst\\b" << "\\bdouble\\b"
                    << "\\benum\\b" << "\\bexplicit\\b"
                    << "\\bfriend\\b" << "\\binline\\b"
                    << "\\bint\\b" << "\\blong\\b"
                    << "\\bnamespace\\b" << "\\boperator\\b"
                    << "\\bprivate\\b" << "\\bprotected\\b"
                    << "\\bpublic\\b" << "\\bshort\\b"
                    << "\\bsignals\\b" << "\\bsigned\\b"
                    << "\\bslots\\b" << "\\bstatic\\b"
                    << "\\bstruct\\b" << "\\btemplate\\b"
                    << "\\btypedef\\b" << "\\btypename\\b"
                    << "\\bunion\\b" << "\\bunsigned\\b"
                    << "\\bvirtual\\b" << "\\bvoid\\b"
                    << "\\bvolatitle\\b" << "\\bbool\\b";
    //儲存c++語法中的關鍵字的匹配規則
    foreach (const QString& pattern, keywordPatterns) {
        rule.pattern = QRegularExpression(pattern);
        rule.format = keywordFormat;
        highlightingRules.append(rule);
    }

    //類名匹配規則以Q開頭的
    classFormat.setFontWeight(QFont::Bold);
    classFormat.setForeground(Qt::darkMagenta);
    rule.pattern = QRegularExpression("\\bQ[A-Za-z]+\\b");
    rule.format = classFormat;
    highlightingRules.append(rule);

    //有註釋的匹配規則
    singleLineCommentFormat.setForeground(Qt::red);
    rule.pattern = QRegularExpression("//[^\n]*");
    rule.format = singleLineCommentFormat;
    highlightingRules.append(rule);

    //多行註釋
    multiLineCommentFormat.setForeground(Qt::red);

    //標頭檔案匹配規則
    quotationFormat.setForeground(Qt::darkGreen);
    rule.pattern = QRegularExpression("\".*\"");
    rule.format = quotationFormat;
    highlightingRules.append(rule);

    //函式名稱匹配規則
    functionFormat.setFontItalic(true);
    functionFormat.setForeground(Qt::blue);
    rule.pattern = QRegularExpression("\\b[A-Za-z0-9]+(?=\\()");
    rule.format = functionFormat;
    highlightingRules.append(rule);

    //註釋開始的匹配
    commentStartExpression = QRegularExpression("/\\*");
    //註釋結束的匹配
    commentEndExpression = QRegularExpression("\\*/");
}

void Highlighter::highlightBlock(const QString &text)
{
    foreach (const HighlightingRule &rule, highlightingRules) {
        //對文字進行正則表示式匹配 並返回匹配到的第一個匹配結果的迭代器
        QRegularExpressionMatchIterator matchIterator =
                rule.pattern.globalMatch(text);
        while (matchIterator.hasNext()) {
            /*
             *QRegularExpressionMatch類提供了根據字串匹配QRegularExpression的結果。
             */
            QRegularExpressionMatch match = matchIterator.next();
            qDebug() << text << " <<<>>>> " << match.capturedTexts();
            //設定高亮的格式
            setFormat(match.capturedStart(0)
                      ,match.capturedEnd(0),
                                          rule.format);
        }
    }
    setCurrentBlockState(0);
    int startIndex = 0;
    if(previousBlockState() != 1)
        startIndex = text.indexOf(commentStartExpression);
    while (startIndex >= 0) {
        QRegularExpressionMatch match = commentEndExpression.match(text,startIndex);
        int endIndex = match.capturedStart();
        int commentLength = 0;
        if(endIndex == -1){
            setCurrentBlockState(1);
            commentLength = text.length() - startIndex;
        }else{
            commentLength = endIndex - startIndex +
                    match.capturedLength();
        }
        setFormat(startIndex,commentLength,multiLineCommentFormat);
        startIndex = text.indexOf(commentStartExpression,
                                  startIndex+commentLength);
    }
}
void MainWindow::setupEditor()
{
    QFont font;
    font.setFamily("Courier");
    font.setFixedPitch(true);
    font.setPointSize(10);

    editor = new QTextEdit;
    editor->setFont(font);

    //這裡先把自定義的註冊進去 告訴文件物件 使用這個進行高亮操作
    hightlighter = new Highlighter(editor->document());

    QFile file(":/src/mainwindow.h");
    if(file.open(QIODevice::ReadOnly|QIODevice::Text))
        editor->setPlainText(file.readAll());
    else
        qDebug() << "11111";
}

4、QTextCursor:提供一個API來訪問和修改QTextDocuments

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QTextEdit *textEdit = new QTextEdit(QString("hello world!hello Qt!"));
    setCentralWidget(textEdit);
    resize(400,300);

    //先拿到游標物件
    QTextDocument *doc = textEdit->document();
    QTextCursor *cursor = new QTextCursor(doc);

    qDebug() << "anchor=" << cursor->anchor() << " position=" << cursor->position();
    qDebug() << "atBlockEnd=" << cursor->atBlockEnd() << " atBlockStart="<< cursor->atBlockStart();
    qDebug() << "atEnd=" << cursor->atEnd() << " atStart="<< cursor->atStart();

    //編輯操作
    cursor->beginEditBlock();
    cursor->insertText("This is ");
    cursor->insertText("Insert ");
    cursor->endEditBlock();

    //返回游標所在的block的number
    qDebug() << "blockNumber=" << cursor->blockNumber();

    //返回游標所在行的列號
    qDebug() << "columnNumber=" << cursor->columnNumber();

    qDebug() << "hasComplexSelection=" << cursor->hasComplexSelection();
    //返回是否選擇了內容
    qDebug() << "hasSelection=" << cursor->hasSelection();

    //在當前游標的位置插入一個空的block 相當於換行的操作
    cursor->insertBlock();

    //插入一個html文字
    cursor->insertHtml("<font color='red'>insertHtml</font>");
    cursor->insertBlock();
    //插入一個圖片
    cursor->insertImage(":/image/任務管理-我的任務-任務查詢查詢不到已經建立的任務.png");
    qDebug() << "isNull=" << cursor->isNull();
    cursor->insertBlock();

    cursor->joinPreviousEditBlock();
    cursor->insertHtml("</b><font color='blue'>joinPreviousEditBlock</font></b>");
    cursor->endEditBlock();

    qDebug() << "keepPositionOnInsert="<<cursor->keepPositionOnInsert();

    //把游標移動到開頭
    cursor->movePosition(QTextCursor::StartOfLine);
    //移動游標不選擇
    cursor->movePosition(QTextCursor::EndOfWord,QTextCursor::MoveAnchor);
    //移動游標並且選擇移動範圍內的內容
    cursor->movePosition(QTextCursor::EndOfLine,QTextCursor::KeepAnchor);
    //介面要顯示出來需要設定一下
    textEdit->setTextCursor(*cursor);

    //游標在block中的位置
    qDebug()<< "positionInBlock=" << cursor->positionInBlock() <<
               " " << cursor->position()-cursor->block().position();

    //刪除選中的文字
    cursor->removeSelectedText();

    //根據選中型別來選中文件中的內容
//    cursor->select(QTextCursor::Document);
    cursor->select(QTextCursor::WordUnderCursor);
    //更新下游標 才能看出來是不是選中了
    textEdit->setTextCursor(*cursor);

    //返回選中的位置
    qDebug() << "selectionStart=" << cursor->selectionStart()
             << " selectionEnd=" << cursor->selectionEnd();

    //是否讓游標不隨著插入的文字移動,始終保持插入前的位置不變 預設是false
    cursor->setKeepPositionOnInsert(false);

    //使用m指定的MoveMode將游標移動到pos指定的文件中的絕對位置。游標位於字元之間。
    cursor->setPosition(1,QTextCursor::MoveAnchor);
    //更新
    textEdit->setTextCursor(*cursor);
}

5、QTextDocument:核心類,儲存富文字資料

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QTextEdit *edit = new QTextEdit;
    QTextDocument *doc = edit->document();
    //獲得根框架
    QTextFrame *root_frame = doc->rootFrame();
    //獲得根框架的格式
    QTextFrameFormat root_frame_format = root_frame->frameFormat();
    root_frame_format.setBorderBrush(Qt::darkBlue);//設定邊框顏色
    root_frame_format.setBorder(5);//設定邊框大小
    root_frame->setFrameFormat(root_frame_format);

    //自定義一個框架格式
    QTextFrameFormat frame_format;
    frame_format.setBackground(Qt::yellow);//設定背景色
    frame_format.setMargin(10);//設定外部的邊距
    frame_format.setPadding(5);//設定內部的填充
    frame_format.setBorder(2);//設定邊框寬度
    frame_format.setBorderStyle(QTextFrameFormat::BorderStyle_Solid);//設定邊框樣式
    //設定這個自定義框架是在哪個位置
    frame_format.setPosition(QTextFrameFormat::FloatRight);//右側
    //根據寬度型別來設定該框架的寬度
    frame_format.setWidth(QTextLength(QTextLength::PercentageLength,40));//寬度設定

    QTextCursor cursor = edit->textCursor();

    cursor.insertText("A company");
    cursor.insertBlock();
    cursor.insertText("321 City Street");
    cursor.insertBlock();
    cursor.insertFrame(frame_format);
    cursor.insertText("Industry Park");
    cursor.insertBlock();
    cursor.insertText("Another country");
    edit->setTextCursor(cursor);

    //把內容遍歷出來
    for(auto block=root_frame->begin();!block.atEnd(); ++block){
        if(block.currentBlock().isValid()){
            qDebug() << block.currentBlock().text();
        }else if(block.currentFrame()){
            qDebug() << "是一個框架";
            for(auto frame_block = block.currentFrame()->begin(); !frame_block.atEnd(); ++frame_block){
                if(frame_block.currentBlock().isValid()){
                    qDebug() << frame_block.currentBlock().text();
                }else{
                    qDebug() << "else";
                }
            }
        }
    }

    //遍歷所以block 包括每個frame中預設的空的
    qDebug() << "doc->blockCount()=" << doc->blockCount();
    QTextBlock block = doc->firstBlock();
    for(int i = 0; i < doc->blockCount(); ++i){
        qDebug()<< QString("block num:%1 block first line number:%2 block length:%3 text:")
                   .arg(i).arg(block.firstLineNumber()).arg(block.length())
                   << block.text();
        block = block.next();
    }

    //獲取第2個block的開頭
    QTextBlock insert_block = doc->firstBlock().next();
    cursor.setPosition(insert_block.position()+insert_block.length()-1);
    cursor.insertText("change cursor postion and insert");

    //將游標設定到第3個block的開頭
//    cursor.setPosition(insert_block.position()+insert_block.length());
    cursor.setPosition(insert_block.next().position());
    cursor.insertText("change cursor postion and insert");

    setCentralWidget(edit);
    resize(400,300);
}
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    //先不用介面展示
    QTextDocument *doc = new QTextDocument;
    QTextCursor *cursor = new QTextCursor(doc);
    //文件本身是有一個文字塊的 可以通過框架來獲得
    QTextFrame *root_frame = doc->rootFrame();
    QTextBlock block = root_frame->begin().currentBlock();
    qDebug() << "此時文字塊="<<block.text();
    //通過游標向文字塊中插入文字
    cursor->insertText("aaa");
    block = root_frame->begin().currentBlock();
    qDebug() << "插入後的文字塊="<<block.text();
    //插入一個新的文字塊 游標換行了 然後在此block中插入資料
    cursor->insertBlock();
    cursor->insertText("bbbb");
    for(int i = 0; i < 10; ++i){
        cursor->insertText("cccccccccccccccccccc");
    }
    qDebug() << "第2個block的長度="<<root_frame->begin().currentBlock().next().length();
    qDebug() << "第2個block的行數="<<root_frame->begin().currentBlock().next().lineCount();
    qDebug() << "第2個block的blockNumber="<<root_frame->begin().currentBlock().next().blockNumber();
    //插入一個自定義的frame 插入之後 除了frame自帶一個block,在frame的最後還有一個blcok
    QTextFrameFormat format = root_frame->frameFormat();
    format.setBorder(3);
    cursor->insertFrame(format);
    cursor->setPosition(root_frame->begin().currentBlock().next().next().position());
    cursor->insertText("dddd");
    cursor->setPosition(root_frame->begin().currentBlock().next().next().next().position());
    cursor->insertText("eeee");
    qDebug() << doc->blockCount();


    QTextEdit *edit = new QTextEdit;
    edit->setDocument(doc);
    edit->setTextCursor(*cursor);
    setCentralWidget(edit);
    resize(300,200);
}

6、QTextDocumentFragment:表示來自QTextDocument的富文字的片段,可以將該片段通過cursor插入到文件中去,並且只有當文件中的某個內容被選中時,可以通過獲取選中的片段來解析獲取選中的內容

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QTextDocument *doc = new QTextDocument;
    QTextCursor *cursor = new QTextCursor(doc);
    QTextDocumentFragment fragment = QTextDocumentFragment::fromPlainText("hello world");
//向文件中插入片段    
cursor->insertFragment(fragment);
//獲取選中的片段
    cursor->select(QTextCursor::Document);
    qDebug() << cursor->selection().toPlainText();
    cursor->clearSelection();
    cursor->insertBlock();
    fragment = QTextDocumentFragment::fromHtml("<font color='red'>hello Qt</font>");
    cursor->insertFragment(fragment);
    cursor->select(QTextCursor::LineUnderCursor);
    qDebug() << cursor->selection().toHtml();
    cursor->clearSelection();

    QTextEdit *edit = new QTextEdit;
    edit->setDocument(doc);
    edit->setTextCursor(*cursor);
    setCentralWidget(edit);
}

7、QTextDocumentWriter:與格式無關的介面,用於將QTextDocument寫入檔案或其他裝置

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    //獲取支援的寫入格式
    qDebug() << QTextDocumentWriter::supportedDocumentFormats();//("HTML", "ODF", "plaintext")
    QTextDocumentWriter writer("a.txt");
    QTextCodec* gb2312Codec = QTextCodec::codecForName("gb2312");
    writer.setCodec(gb2312Codec);
    writer.write(QTextDocumentFragment::fromPlainText("你好啊"));

    //把寫入的檔案讀出來
    QFile file("a.txt");
    file.open(QIODevice::ReadOnly);
    QByteArray array = file.readAll();
    qDebug() << gb2312Codec->toUnicode(array);

    QTextDocumentWriter writerOdf("a.doc","odf");//xlsx xls 試下了 好像不行 有可能方法錯了
    writerOdf.write(QTextDocumentFragment::fromPlainText("你好啊"));

    QTextDocumentWriter writerHtml("a.html","HTML");
    writerHtml.write(QTextDocumentFragment::fromHtml("<b><font color='red'>你好啊</font></b>"));
}

8、QTextBlockFormat: 儲存QTextDocument中的文字塊的格式資訊。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QTextDocument *doc = new QTextDocument;
    QTextCursor *cursor = new QTextCursor(doc);

    //自定義一個blcok格式
    QTextBlockFormat blockFormat;
    blockFormat.setAlignment(Qt::AlignRight);//右對齊
    blockFormat.setBackground(QBrush(Qt::yellow));//背景色
    blockFormat.setBottomMargin(10);//外部距離底部的空間
    blockFormat.setForeground(QBrush(Qt::lightGray));//前景色
    blockFormat.setIndent(4);//縮排
    blockFormat.setLayoutDirection(Qt::RightToLeft);//文字從右到左
    blockFormat.setLeftMargin(10);//外部距離左邊的空間
    blockFormat.setLineHeight(50,QTextBlockFormat::LineDistanceHeight);//這將在行之間新增指定的高度50畫素點
    blockFormat.setNonBreakableLines(true);//設定是不可以被打亂的
    blockFormat.setTopMargin(50);
    blockFormat.setRightMargin(100);
    blockFormat.setTextIndent(10);//為塊中的第一行設定縮排。
    cursor->insertBlock(blockFormat);
    cursor->insertText("這幾天權健新聞火了,昔日風光無比的保健品大拿,今日面臨著各項指控,高法還指認其進涉嫌傳銷,可嘆法網恢恢疏而不漏啊。今天做生意,講的是商業模式,網際網路的發展形成了很多種商業模式,比如社交,比如B2B,B2C等,但是,在網際網路大行其道之前,中國常看到的就是一種直銷的商業模式,直銷接著就出來變種,變成了傳銷,直銷和傳銷都是拉人頭,只不過直銷還是有商品為主,而傳銷感覺商品只是其中一個引子而已,純粹就是賺人頭費,層層的組織,最終讓人們死心塌地活在傳銷生態圈裡不能自拔,曾幾何時,見面就跟人談產品,讓人無比側目。");
    cursor->insertBlock(QTextBlockFormat());
    cursor->insertText("這個是正常的");

    QTextEdit *edit = new QTextEdit;
    edit->setDocument(doc);
    edit->setTextCursor(*cursor);
    setCentralWidget(edit);
    resize(500,400);
}

9、QTextCharFormat:儲存QTextDocument中的字元的格式資訊。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QTextEdit *edit = new QTextEdit;
    QTextDocument *doc = edit->document();
    QTextCursor *cursor = new QTextCursor(doc);

    //自定義一個型別
    QTextCharFormat charFormat;
    charFormat.setAnchorHref("http://example.com/index.html");
    charFormat.setAnchor(true);
    QFont font;
    font.setBold(true);
    font.setUnderline(true);
    charFormat.setFont(font);
    charFormat.setToolTip("這是hello world");

    cursor->insertBlock();
    cursor->insertText("hello world",charFormat);
    edit->setTextCursor(*cursor);
    setCentralWidget(edit);
    resize(400,100);
}

10、QTextFormat:儲存QTextDocument中文字的格式資訊。QTextFormat是一個通用類,用於描述QTextDocument部分內容的格式。派生類QTextCharFormat、QTextBlockFormat、QTextListFormat和QTextTableFormat通常更有用,它們描述了應用於文件特定部分的格式。

11、QTextFrameFormat:儲存QTextDocument中的框架的格式資訊。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QTextEdit *edit = new QTextEdit;
    QTextDocument *doc = edit->document();
    QTextCursor *cursor = new QTextCursor(doc);

    cursor->insertText("這是我的框架格式");
    cursor->insertBlock();
    //自定義格式
    QTextFrameFormat format;
    format.setBackground(QBrush(Qt::blue));
    format.setBorder(3);
    format.setBorderBrush(QBrush(Qt::red));
    format.setTopMargin(5);
    format.setBottomMargin(5);
    format.setLeftMargin(5);
    format.setRightMargin(5);
//    format.setHeight(QTextLength(QTextLength::FixedLength,100));
    format.setPadding(30);
    format.setPosition(QTextFrameFormat::FloatRight);
    format.setWidth(QTextLength(QTextLength::PercentageLength,40));
    format.setBorderStyle(QTextFrameFormat::BorderStyle_Dotted);
    cursor->insertFrame(format);
    cursor->insertText("啊啊啊啊啊啊啊");
    setCentralWidget(edit);
    edit->setTextCursor(*cursor);
    resize(400,300);
}

這張圖特別形象說明了文字或者框架的圍繞佈局

12、QTextImageFormat:儲存QTextDocument中的影象的格式資訊。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QTextDocument *doc = new QTextDocument;
    QTextCursor *cursor = new QTextCursor(doc);

    //自定義一個圖片格式
    QTextImageFormat imageFormat;
    QImage image(":/image/v2-e687e8a3299301852036625042c0d21f_hd.jpg");
    imageFormat.setName(":/image/v2-e687e8a3299301852036625042c0d21f_hd.jpg");
    imageFormat.setHeight(image.height()*0.3);
    imageFormat.setWidth(image.width()*0.3);
    cursor->insertBlock();
    cursor->insertImage(imageFormat);

    QTextEdit *edit = new QTextEdit;
    edit->setDocument(doc);
    edit->setTextCursor(*cursor);
    setCentralWidget(edit);
    resize(400,300);
}

13、QTextLength:表示了QTextDocument中不同型別的文字長度。使用方法詳見上面

14、QTextListFormat:儲存QTextDocument中的列表的格式資訊。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QTextEdit *edit = new QTextEdit;
    QTextDocument *doc = edit->document();
    QTextCursor *cursor = new QTextCursor(doc);
    cursor->beginEditBlock();
    cursor->insertText("hello world");
    cursor->insertText("aaaa");
    cursor->endEditBlock();
    QTextBlock listblock = cursor->block();
    cursor->insertBlock();
    cursor->setPosition(listblock.length()-1);
    //定義一個TextListFormat
    QTextListFormat format;
    format.setBackground(QBrush(Qt::blue));
    format.setIndent(1);//設定縮排
    format.setLayoutDirection(Qt::RightToLeft);//設定文字方向
    format.setStyle(QTextListFormat::ListDecimal);//設定開頭以數字表示
    format.setNumberPrefix("(");//字首
    format.setNumberSuffix(")");//字尾
    QTextList *list = cursor->insertList(format);
    cursor->insertText("bbbb");
    //但是如何跳出這個textlist呢?
    cursor->setPosition(cursor->block().next().position());

    edit->setTextCursor(*cursor);
    setCentralWidget(edit);
    resize(300,200);
}

15、QTextTableCellFormat:儲存QTextDocument中的表格單元的格式資訊

16、QTextTableFormat:儲存QTextDocument中的表格的格式資訊

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QTextDocument *doc = new QTextDocument;
    QTextCursor cursor = QTextCursor(doc);
    cursor.insertText("hello world");
    //根據表格式來建立表
    QTextTableFormat tableFormat;
    tableFormat.setBackground(QBrush(Qt::yellow));
    tableFormat.setBorder(2);
    tableFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Solid);
    //表格的對齊方式 注意不是表格內的內容
    tableFormat.setAlignment(Qt::AlignCenter);
    tableFormat.setPadding(2);
    tableFormat.setCellSpacing(3);

    cursor.insertTable(10,4,tableFormat);

    QTextEdit *edit = new QTextEdit;
    edit->setDocument(doc);
    edit->setTextCursor(cursor);
    setCentralWidget(edit);
    resize(300,200);
}

17、QTextInlineObject:表示QAbstractTextDocumentLayout及其實現中的內聯物件。通常,您不需要建立QTextInlineObject。QAbstractTextDocumentLayout在實現自定義佈局時使用它來處理內聯物件。

18、QTextLayout:用於佈局和呈現文字。QTextLayout可用於建立具有給定寬度的QTextLine例項序列,並可在螢幕上獨立定位它們。一旦佈局完成,這些線條就可以繪製在繪圖裝置上。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    resize(300,200);
}

MainWindow::~MainWindow()
{

}

void MainWindow::paintEvent(QPaintEvent *event)
{
    QTextLayout *layout = new QTextLayout;
    //要進行佈局的文字內容
    layout->setText("hello world 11111111111111111111111111111111");
    //一般設定可以快取
    layout->setCacheEnabled(true);
    //更改下文字的字型格式
    QFont font;
    font.setUnderline(true);
    layout->setFont(font);
    //開始佈局
    layout->beginLayout();
    int height = 0;
    int lineWidth = 100;
    int startPoint = 0;
    while (1) {
        //先建立一個行
        QTextLine line = layout->createLine();
        if (!line.isValid())
            break;

        //設定這一行的文字寬度
        line.setLineWidth(lineWidth);
        //高度需要疊加計算 否則文字會被佈局到一起
        height += 10;
        //設定行的起點和高度
        line.setPosition(QPointF(30*(++startPoint), height));
        //計算最終的高度
        height += line.height();
    }

    layout->endLayout();
    QPainter painter(this);
    layout->draw(&painter, QPoint(0, 50));
}

19、QTextLine:表示QTextLayout中的一行文字。

20、QTextList:提供QTextDocument中修飾過的專案列表。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QTextEdit *edit = new QTextEdit;
    QTextDocument *doc = edit->document();
    QTextCursor *cursor = new QTextCursor(doc);
    cursor->insertText("hello world");
    //有2中建立QTextList的方式
    //createList函式:獲取游標當前block的內容,並將其轉換為新列表的第一項。
    cursor->createList(QTextListFormat::ListDisc);
    cursor->insertText("aaaa");
    //繼續在此列表中新增資料
    cursor->insertBlock();
    cursor->insertText("bbbb");
    //insertList函式:在文件的游標位置插入一個block,並將其作為列表中的第一項。
    cursor->insertList(QTextListFormat::ListCircle);
    cursor->insertText("hello Qt");
    cursor->insertBlock();
    cursor->insertText("cccc");
    edit->setTextCursor(*cursor);
    setCentralWidget(edit);
    resize(400,300);
}

21、QTextBlock:為QTextDocument中的文字片段提供了一個容器。

22、QTextBlockGroup:為QTextDocument中的文字塊提供了一個容器。

23、QTextBlockUserData:將自定義資料與文字塊相關聯。

24、QTextFragment:使用一個QTextCharFormat儲存QTextDocument中的一段文字。

25、QTextFrame:表示QTextDocument中的一個框架。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QTextEdit *edit = new QTextEdit;
    QTextDocument *doc = edit->document();
    QTextCursor *cursor = new QTextCursor(doc);
    cursor->insertText("aaaa");
    cursor->insertBlock();

    //必須先定義一個框架格式
    QTextFrameFormat frameFormat;
    frameFormat.setBorder(3);
    //建立在文件中新增框架
    QTextFrame *frame = cursor->insertFrame(frameFormat);
    cursor->insertText("bbbb");
    frameFormat.setBorder(2);
    frameFormat.setBorderBrush(QBrush(Qt::red));
    frameFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Dotted);
    QTextFrame *childFrame = cursor->insertFrame(frameFormat);
    cursor->insertText("cccc");
    qDebug()<< "子框架個數:"<<frame->childFrames().size();
    cursor->setPosition(cursor->block().next().position());
    cursor->insertText("dddd");

    //返回框架中的第一個游標位置。
    QTextCursor frameCursor = childFrame->parentFrame()->firstCursorPosition();
    edit->setTextCursor(frameCursor);
    //返回框架中的最後的游標位置。
    frameCursor = childFrame->parentFrame()->lastCursorPosition();
    edit->setTextCursor(frameCursor);
    setCentralWidget(edit);
//    edit->setTextCursor(*cursor);
    resize(300,200);
}

26、QTextObject:用於不同型別物件的基類,這些物件可以將QTextDocument的各個部分組合在一起。

27、QTextFrame::iterator: 迭代器類為讀取QTextFrame的內容提供了一個迭代器。

28、QTextBlock::iterator: 為讀取QTextBlock的內容提供了一個迭代器。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QTextEdit *edit = new QTextEdit;
    QTextDocument *doc = edit->document();
    QTextCursor cursor = edit->textCursor();
    cursor.insertText("hello world! hello Qt!");
    cursor.insertText("111222333444");
    QTextBlock block = cursor.block();//doc->firstBlock();
    QTextBlock::iterator it;
    for(it = block.begin(); !it.atEnd(); ++it){
        QTextFragment fragment = it.fragment();
        if(fragment.isValid())
            qDebug() << fragment.text();
    }
    setCentralWidget(edit);
    edit->setTextCursor(cursor);
    resize(300,200);
}

29、QTextOption:可以設定富文字的一般屬性。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QTextEdit *edit = new QTextEdit;
    QTextDocument *doc = edit->document();
    doc->setPlainText("hello world!111111");

    //定義一個封裝文字格式的物件
    QTextOption option;
//    option.setAlignment(Qt::AlignCenter);
    option.setTextDirection(Qt::RightToLeft);
    option.setWrapMode(QTextOption::WrapAnywhere);
    doc->setDefaultTextOption(option);

    setCentralWidget(edit);
    resize(300,200);
}

30、QTextTable:表示QTextDocument中的一個表。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QTextEdit *edit = new QTextEdit;
    QTextDocument *doc = edit->document();
    QTextCursor cursor = edit->textCursor();
    cursor.insertText("hello world");
    //不含表格式建立 游標落在第一行第一列中
    QTextTable *table = cursor.insertTable(5,5);
    //右側插入2列
    table->insertColumns(4,2);
    //下邊插入2行
    table->insertRows(4,2);
    //合併單元格 指定下標
    table->mergeCells(0,0,2,5);
    cursor.insertText("合併000000000000000000000000");
    //合併單元格 合併由提供的遊標選擇的單元格。
    cursor.movePosition(QTextCursor::NextRow);
    cursor.movePosition(QTextCursor::NextCell,QTextCursor::KeepAnchor);
    table->mergeCells(cursor);
    cursor.insertText("合併111111111111111111111111");
    //將個單元格分割成多行多列 只可能分割跨多個行或列的單元格,例如使用mergeCells()合併的行。
    table->splitCell(0,0,1,2);

    //設定一個空的格式
    table->setFormat(QTextTableFormat());


    //游標如何跳出這個表
//    for(int i = 1; i < table->rows(); ++i)
//        cursor.movePosition(QTextCursor::NextRow);
//    for(int i = 1; i < table->columns(); ++i)
//        cursor.movePosition(QTextCursor::NextCell);
//    cursor.movePosition(QTextCursor::NextBlock);
//    cursor.insertBlock();
//    cursor.insertText("aaaa");

    setCentralWidget(edit);
    edit->setTextCursor(cursor);
    resize(300,200);
}

31、QTextTableCell:表示QTextTable中的單元格的屬性。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    resize(300,200);
    QTextEdit *edit = new QTextEdit;
    QTextDocument *doc = edit->document();
    QTextCursor cursor = edit->textCursor();
    QVector<QTextLength> vector;
    for(int i = 0; i < 5; ++i)
        vector << QTextLength(QTextLength::PercentageLength,20);
    QTextTableFormat format;
    format.setColumnWidthConstraints(vector);
    format.setCellSpacing(1);
    QTextTable *table = cursor.insertTable(5,5,format);

    //賦值
    for(int i = 0; i < 5; ++i){
        for(int j = 0; j < 5; ++j){
            //設定下字型格式
            QTextBlockFormat blockFormat;
            blockFormat.setAlignment(Qt::AlignRight);
            cursor.setBlockFormat(blockFormat);
            QTextCharFormat charFormat;
            charFormat.setFontFamily("宋體");
            charFormat.setFontItalic(true);
            charFormat.setFontUnderline(true);
            cursor.setCharFormat(charFormat);
            cursor.insertText(QString("row%1,col%2").arg(i).arg(j));
            QTextTableCell cell = table->cellAt(cursor);
            qDebug() << "(" << cell.row() << "," << cell.column() << ")";
            QTextCursor tmp = cell.firstCursorPosition();
            qDebug() << "first tmp = " << tmp.position();
            tmp = cell.lastCursorPosition();
            qDebug() << "last tmp = " << tmp.position();
            if(j == 4)
                continue;
            cursor.movePosition(QTextCursor::NextCell);
        }
        if(i == 4)
            continue;
        cursor.movePosition(QTextCursor::NextRow);
    }
    edit->setTextCursor(cursor);
    setCentralWidget(edit);
}

32、QPlainTextDocumentLayout:為QTextDocument實現純文字佈局

33、QPlainTextEdit:一個小部件,用於編輯和顯示純文字。

class LineNumberArea;

class CodeEditor : public QPlainTextEdit
{
    Q_OBJECT

public:
    CodeEditor(QWidget *parent = 0);
    ~CodeEditor();

    void lineNumberAreaPaintEvent(QPaintEvent *event);
    int lineNumberAreaWidth();

protected:
    void resizeEvent(QResizeEvent *event) override;

private slots:
    void updateLineNumberAreaWidth(int newBlockCount);
    void highlightCurrentLine();
    void updateLineNumberArea(const QRect & , int);
private:
    QWidget *lineNumberArea;
};

class LineNumberArea : public QWidget
{
public:
    LineNumberArea(CodeEditor *editor):QWidget(editor)
    {
         codeEditor = editor;
    }

    QSize sizeHint()const override
    {
        return QSize(codeEditor->lineNumberAreaWidth(),0);
    }

protected:
    void paintEvent(QPaintEvent *event) override
    {
        codeEditor->lineNumberAreaPaintEvent(event);
    }

private:
    CodeEditor *codeEditor;
};
CodeEditor::CodeEditor(QWidget *parent)
    : QPlainTextEdit(parent)
{
    //建立行號顯示控制元件
    lineNumberArea = new LineNumberArea(this);

    //當換行時更新行號
    connect(this,SIGNAL(blockCountChanged(int)),
            this,SLOT(updateLineNumberAreaWidth(int)));

    connect(this,SIGNAL(updateRequest(QRect,int)),
            this,SLOT(updateLineNumberArea(QRect,int)));
    connect(this,SIGNAL(cursorPositionChanged()),
            this, SLOT(highlightCurrentLine()));

    updateLineNumberAreaWidth(0);
    highlightCurrentLine();
}

CodeEditor::~CodeEditor()
{

}

void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
{
    qDebug() << event->rect();
    QPainter painter(lineNumberArea);
    painter.fillRect(event->rect(),Qt::lightGray);

    QTextBlock block = firstVisibleBlock();
    int blockNumber = block.blockNumber();
    int top = (int)blockBoundingGeometry(block).translated(contentOffset()).top();
    int bottom = top + (int)blockBoundingRect(block).height();

    while (block.isValid() && top <= event->rect().bottom()) {
        if(block.isVisible() && bottom >= event->rect().top()){
            QString number = QString::number(blockNumber+1);
            painter.setPen(Qt::black);
            painter.drawText(0,top,lineNumberArea->width(),fontMetrics().height(),
                             Qt::AlignRight,number);
        }
        block = block.next();
        top = bottom;
        bottom = top + (int)blockBoundingRect(block).height();
        ++blockNumber;
    }
}

int CodeEditor::lineNumberAreaWidth()
{
    int digits = 1;
    int max = qMax(1,this->blockCount());
    while (max >= 10) {
        max /= 10;
        ++digits;
    }
    int space = 3+fontMetrics().width(QLatin1Char('9'))*digits;
    return space;
}

void CodeEditor::resizeEvent(QResizeEvent *event)
{
    QPlainTextEdit::resizeEvent(event);
    QRect cr = contentsRect();
    lineNumberArea->setGeometry(QRect(cr.left(),
                               cr.top(),lineNumberAreaWidth(),
                               cr.height()));
}

void CodeEditor::updateLineNumberAreaWidth(int newBlockCount)
{
    //更新編輯框距離左邊的間距
    setViewportMargins(lineNumberAreaWidth(),0,0,0);
}

void CodeEditor::highlightCurrentLine()
{
    QList<QTextEdit::ExtraSelection> extraSelections;
    if(!isReadOnly()){
        //ExtraSelection結構提供了一種為文件中給定的選擇指定字元格式的方法
        QTextEdit::ExtraSelection selection;
        QColor lineColor = QColor(Qt::yellow).lighter(160);
        selection.format.setBackground(lineColor);
        //FullWidthSelection 表示在選定的字元格式上設定時,將顯示選定文字的整個寬度。
        selection.format.setProperty(QTextFormat::FullWidthSelection,true);
        selection.cursor = textCursor();
        selection.cursor.clearSelection();
        extraSelections.append(selection);
    }
    /*
     * 此函式允許用指定的顏色(指定為選擇)臨時標記文件中的某些區域。這可能非常有用,
     * 例如在程式設計編輯器中,用給定的背景顏色標記一整行文字以表明斷點的存在。
     */
    setExtraSelections(extraSelections);
}

void CodeEditor::updateLineNumberArea(const QRect &rect, int dy)
{
    qDebug() << rect << " "<<dy;
    if(dy){
        //讓行號跟隨編輯框滾動 並且重新繪製
        lineNumberArea->scroll(0,dy);
    }else{
        lineNumberArea->update(0,rect.y(),lineNumberArea->width(),rect.height());
    }

    if(rect.contains(viewport()->rect()))
        updateLineNumberAreaWidth(0);
}
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QPlainTextEdit *edit = new QPlainTextEdit("hello world111222333");
    //設定換行格式
//    edit->setLineWrapMode(QPlainTextEdit::NoWrap);//不換行
    edit->setWordWrapMode(QTextOption::WrapAnywhere);//任意處換行
    //插入文字 在當前游標前面
    edit->insertPlainText("555666");
    //追加文字 在文件最後 並且換行追加
    edit->appendPlainText("777888");
    edit->appendPlainText("999000");

    //查詢並且選中文字
    QTextCursor cursor = edit->textCursor();
    edit->find("888");
    setCentralWidget(edit);
    resize(300,200);
}

34、QTextBrowser:提供了具有超文字導航的富文字瀏覽器。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{

    QTextBrowser *browser = new QTextBrowser;
    browser->setAttribute(Qt::WA_DeleteOnClose);
    setCentralWidget(browser);
    //可以當做編輯框使用
//    browser->setReadOnly(false);
//    browser->setEnabled(true);
    /*
     * 指定QTextBrowser是否應該使用QDesktopServices::openUrl()自動開啟指向外部源的連結,
     * 而不是發出錨點單擊訊號。如果連結的模式既不是檔案也不是qrc,則視為外部連結.
     */
    browser->setOpenExternalLinks(true);//設定為支援使用外部程式開啟url
    /*
     * 此屬性指定QTextBrowser是否應自動開啟使用者試圖通過滑鼠或鍵盤啟用的連結。
     */
    browser->setOpenLinks(true);
    /*
     * 此屬性儲存文字瀏覽器用於查詢支援內容的搜尋路徑
     * QTextBrowser使用這個列表來定點陣圖像和文件。
     */
    browser->setSearchPaths(QStringList()<<"F:/");
    /*
     * 此屬性儲存顯示的文件的名稱。
     * QTextBrowser嘗試在當前源的searchPaths屬性和目錄的路徑中查詢具有指定名稱的文件,
     * 除非該值是一個絕對檔案路徑。
     */
    //載入一個下載好的html來供文字瀏覽器使用
    QUrl url = QUrl::fromLocalFile("F:/【wei375653972的部落格】Qt基礎學習_成為QML大神_Qt常用類學習 - CSDN部落格.html");
    browser->setSource(url);

    /*
     * 請注意,瀏覽器將自動處理到link指定位置的導航,除非將openLinks屬性設定為false,
     * 或者在連線的槽中呼叫setSource()。此機制用於覆蓋瀏覽器的預設導航特性。
     */
    connect(browser,&QTextBrowser::anchorClicked,[=](const QUrl &){
        qDebug() << url.url();
    });

    home = menuBar()->addAction("Home");
    connect(home,&QAction::triggered,browser,&QTextBrowser::home);
    back = menuBar()->addAction("Back");
    connect(back,&QAction::triggered,browser,&QTextBrowser::backward);
    close = menuBar()->addAction("Close");
    connect(close,&QAction::triggered,browser,&QTextBrowser::close);
    connect(browser,&QTextBrowser::destroyed,[=]{
        qDebug() << "被銷燬了?";
    });
}

35、QTextEdit:一個小部件,用於編輯和顯示純文字和富文字。詳見上面