P37-41 QT学习-自学笔记-文本编辑器

参考文章  

hitzsf 博主
  长沙红胖子qt 博主

如何查找电脑上字体名称
 win+r的快捷键打开运行窗口。2、然后在输入框中输入control点击确定。3、在所有控制面板项 右边搜索框 输入“字体”--回车--查看安装的字体。

0-概述

QTextEdit 是一个部件,可以用来展示或编辑纯文本和富文本。

如果用来书写富文本的话,支持html的标签。当然,几个字的富文本,最好使用QLabel 。

纯文本,一行就相当于一个段落。

QTextBrowser是QTextEdit 的子类,功能增加了一个可以导航(添加超链接)。

对于这两种文本编辑器,代码方式有两种,一种是 (??这里我还没弄明白) ,另一种是基于游标来编辑,也就是说必须先获得QTextCursor。

0.1 游标的构造函数有3种:

从文本框QTextBlock中获得   QTextCursor(const QTextBlock &block)

从框架QTextFrame种获得    QTextCursor(QTextFrame *frame)

从文档QTextDocument获得    QTextCursor(QTextDocument *document)

拷贝构造函数和=号赋值重载函数。QTextCursor(const QTextCursor &cursor)

0.2 游标可以插入哪些文档元素

insertBlock  文本块
insertFragment  文本片段
insertFrame 文本框架
insertHtml(const QString &html)  网页

insertList  列表
insertTable(int rows, int columns)  表格,(父类是frame)
insertText(const QString &text)  文本
insertImage 图

0.3 光标位置操作函数

QTextCursor QTextFrame::firstCursorPosition() const

Returns the first cursor position inside the frame.注意,是在框架内的最前面的光标位置。

int QTextFrame::firstPosition() const
Returns the first document position inside the frame.意思跟上面那个方法一样,但是返回整数,意思是文档里的位置,(还是在框架内)。

1.QTextBlock Class -文本块

创建时选择widget 。在widget.h里面添加 

#include<QTextEdit>
#include <QTextCursor>
#include <QTextBlockFormat>

widget.cpp 中代码如下:

1.1 QTextFormat 

描述段落 格式。包括:

setBackground  段落背景 (参数可以是个QColor )

段落缩进 indent 

段落margin  --上下左右 

首行缩进textIndent

1.2  QTextCharFormat

描述字符格式。

格式包括: setFont 字体( 字号,字体,加粗,)

setOverline  上滑线、下划线、

wordSpacing  单词间距、字母间距、

setVerticalAlignment   字符的垂直对齐(默认所有的字母都有一条看不见的基线,平时字母都是在基线中间)

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //the whole size
    resize(900,700);

    //CSDN
    QTextEdit *editor = new QTextEdit(this);

    //my change it bigger
    editor->resize(850,650);

    QTextCursor cursor(editor->textCursor());


    cursor.beginEditBlock();
    

            // cursor.insertText(tr("Character formats"));发现不写tr也行
            cursor.insertText("Character formats");

        //insertBlock重载版本1  作用:重新起一段
        cursor.insertBlock();
            cursor.insertText("Text can be displayed in a variety of different character 
             formats. ");
            cursor.insertText("We can emphasize text by ");
            cursor.insertText("making it italic");


        // QTextBlockFormat Class 先设置block格式再插入文本块
        QTextBlockFormat bf1;

            //设置段落的背景
            bf1.setBackground(QColor(190,150,200));

            //设置行高,第一个参数是一个数字,整数小数都行。第二个参数有0 ,1 2 等多种value ,找                
                  lineHeightTypes可以查询。
            bf1.setLineHeight(120,1);

            //SHEZHI 下边距
            bf1.setBottomMargin(50);

            cursor.setBlockFormat(bf1);

           
            cursor.insertBlock();
            cursor.insertText("setBlockFormat  bf1 bf1  has a purple background color "
                "先设置段落格式,然后插入文本块,然后插入text hah a this is written by me ");



       //自学insertBlock 重载版本2
       //void QTextCursor::insertBlock(const QTextBlockFormat &format)
            QTextBlockFormat bf2;

            //设置段落的背景
            bf2.setBackground(QColor(210,108,120));

            //设置行高,第一个参数是一个数字,整数小数都行。第二个参数有0 ,1 2 等多种value ,找 
                lineHeightTypes可以查询。
                        //只有一行的时候,第二个参数是2必须,不然设置多大都显示不出来
                bf2.setLineHeight(200,1);

                //SHEZHI 下边距
                bf2.setBottomMargin(20);

                //在段落中,首行缩进 参数是一个整数或者浮点数字 可以先测量出字符宽度然后写这个数 
                值*2
                QFontMetrics fm(this->font());
                bf2.setTextIndent(fm.averageCharWidth()*2);


                //设置缩进,这个段落相对于部件的缩进, 参数必须是整数,文档范围的标准缩进
                bf2.setIndent(1);


                cursor.insertBlock(bf2);
                cursor.insertText("QFontMetrics functions calculate the size of characters and strings for a given font. There are three ways you can create a QFontMetrics object:"
"     QFont font('times', 24);QFontMetrics fm(font)   QWidget::fontMetrics() returns the font metrics for a widget's font. This is equivalent to QFontMetrics(widget->font())");


        //自学insertBlock 重载版本3
            //void QTextCursor::insertBlock(const QTextBlockFormat &format, const QTextCharFormat &charFormat)
            //self study :QTextCharFormat

            QTextCharFormat cf1;

                QFont qf1;
                qf1.setOverline(true); //上划线
                qf1.setFamily("Agency FB"); //字体
                qf1.setPointSize(26);

                //设置字体
            cf1.setFont(qf1);

            //设置单词之间的间距, 10比默认的大
            cf1.setFontWordSpacing(10);


            //字符的垂直对齐,是相对于 看不见的默认基线而言的,
                    //因为我弄了上划线,因为我想看到那个线所以设置了往下边对齐
            cf1.setVerticalAlignment(QTextCharFormat::AlignSubScript);
            //这个东西可能会影响字号

        cursor.insertBlock(bf1, cf1);

            cursor.insertText("cursor.insertBlock(bf1, cf1);//自学insertBlock 重载版本3//void QTextCursor::insertBlock(const QTextBlockFormat &format, const QTextCharFormat &charFormat)");

    cursor.endEditBlock();

}


Widget::~Widget()
{
    delete ui;
}

效果:

1.2.1 QTextImageFormat Class

 QTextImageFormat Class是QTextCharFormat的子类,为QTextDocument 类中的图片提供格式。

 2. QTextFragment Class

根据官方帮助文档,每个片段都有一个自己独特的QTextCharFormat。

即:格式不同的字体会被从段落中分割为fragment.

2.1  QTextFragment和block的关系:

 QTextBlock的迭代器就是在各个fragment之间遍历。找到的每一个片段先判断是否有效,然后判断某种属性 。但是一旦插入新块 cursor.insertBlock ,再insertText  那么当前块的迭代器就找不到下一个片段了,例如,我将博主的代码里加入了 cursor.insertBlock 然后迭代器不管放在哪个块里 都找不到别的块里的fragment 了。但是测试结果 和cursor.endEditBlock();

头文件widget.h里添加 
#include<QTextEdit>
#include <QTextCursor>
#include <QTextBlockFormat>
#include <QTextFragment>
#include <QDebug>

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->setupUi(this);
    //the whole size
    resize(900,700);

    //CSDN
    QTextEdit *editor = new QTextEdit(this);


    //my change it bigger 设置自己的偏好字体
    editor->resize(850,650);
    QTextDocument *doc = editor->document();  //获取文本文档
    QFont myfont("Bahnschrift",14);
    doc->setDefaultFont(myfont);
    QTextCursor cursor(editor->textCursor());



    cursor.insertBlock();
        //QTextFragment  片段1 ,
        //首次定义文本字符格式 charFormat变量
            QTextCharFormat chf;

            chf.setForeground(Qt::darkCyan);
            //当前文本光标设置字符格式
            cursor.setCharFormat(chf);
            cursor.insertText("first  sentence1111111");

        //QTextFragment  片段2 ,换一种字体颜色 红色
        //修改 QTextCharFormat  对象
            chf.setForeground(Qt::red);
            cursor.setCharFormat(chf);
            cursor.insertText("second  sentence2222The QTextBlock class provides a container for text fragments in a QTextDocument.");

         
            
            
        // ---注意下面这行代码,如果注释掉,这3个fragment就是一个整block
        // ----如果不注释掉,那么百度超链接就是一个独立的块,打印结果只有百度
//cursor.insertBlock();

            
            
        //第三次定义 QTextCharFormat   字符格式的超链接的使用,字体颜色改成绿色
            chf.setForeground(Qt::green);
            chf.setAnchor(true); //启用锚功能
            chf.setAnchorHref("http://www.baidu.com"); //超链接地址
            chf.setBackground(QColor(120,170,200));  //字体背景
            chf.setFontUnderline(true);  //设置下划线
            cursor.setCharFormat(chf);
            cursor.insertText("this is to baidu Anchor");

            QTextBlock::iterator it;
            for (it = cursor.block().begin(); !(it.atEnd()); ++it) {
                QTextFragment frag = it.fragment();
                if (frag.isValid()) {
                    if(frag.charFormat().isAnchor()){
                        qDebug()<<"find anchor";
                        qDebug()<<frag.text() << frag.charFormat().anchorHref();

                    }
                    else{
                         qDebug() <<"未找到超链接";
                        qDebug() <<frag.text() ;
                    }
                }
            }
}

Widget::~Widget()
{
    delete ui;
}

 效果图:

qDebug打印结果:

未找到超链接
"first  sentence1111111"
未找到超链接
"second  sentence2222The QTextBlock class provides a container for text fragments in a QTextDocument."
find anchor
"this is to baidu Anchor" "http://www.baidu.com"

原文代码Qt 富文本处理(10):文本片段和文本字符格式_qtextcharformat-CSDN博客 

 2.2  QTextFragment构造函数

QTextFragment(const QTextFragment &other)
QTextFragment()

3. QTextDocumentFragment Class

一段富文本的片段。可以插入QTextDocument。 这个片段可以从QTextDocument中创建,可以从QTextCursor 选择,或者从另一个片段拷贝构造。还可以被静态函数创建,这两个函数是fromPlainText() and fromHtml().

暂时还不知道有什么用处

QTextFragment和 QTextDocumentFragment可以混合在一起

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //the whole size
    resize(900,700);

    //CSDN
    QTextEdit *editor = new QTextEdit(this);


    //my change it bigger 设置自己的偏好字体
    editor->resize(850,650);
    QTextDocument *doc = editor->document();  //获取文本文档
    QFont myfont("Bahnschrift",14);
    doc->setDefaultFont(myfont);
    QTextCursor cursor(editor->textCursor());


        cursor.insertBlock();

        //首次定义文本字符格式 charFormat变量
            QTextCharFormat chf;

        //然后插入新片段
        chf.setBackground(QColor(100,190,200));
        cursor.setCharFormat(chf);
        cursor.insertText("this is QTextFragment hello world hello worldhello worldhello worldhello worldhello world");
        QString str222=cursor.selectedText();


    QTextDocumentFragment  docfrag2= QTextDocumentFragment ::fromHtml("<h2>this is QTextDocumentFragment  HTML 5 new attributes </h2>");

    cursor.insertFragment(docfrag2);


}

Widget::~Widget()
{
    delete ui;
}

3.1 构造函数

3.1.1拷贝构造函数和 等号赋值重载 operator =
3.1.2     空的  QTextDocumentFragment()
 3.1.3  QTextDocumentFragment(const QTextDocument *document)
 3.1.4 QTextDocumentFragment(const QTextCursor &cursor)

第 3 、 4种还没有找到相应代码

3.2 插入文本片段

 void QTextCursor::insertFragment(const QTextDocumentFragment &fragment)

QTextDocumentFragment  docfrag2= QTextDocumentFragment ::fromHtml("<h2>this is QTextDocumentFragment  HTML 5 new attributes </h2>");

cursor.insertFragment(docfrag2);

 3.3 从光标接口获得文档片段

QTextDocumentFragment docfrag=cursor.selection();

 一般来说刚打开,肯定用户什么文字都没有选择,所以这个方法一般用在鼠标拖拽选中的事件里?

QTextDocumentFragment docfrag=cursor.selection();
    if(docfrag.isEmpty()){
       qDebug()<<"selecet  nothing ";
    }
    else{
        qDebug()<<str222;
    }

4. QTextFrame   Class

文档框架为文档正文提供结构。作为文档元素的一般性的容器,创建方式通常是QTextCursor::insertFrame()。

框架可以为富文本构建层级结构。一个document有一个根框架,然后每个框架都有一个父框架和所有子框架的列表(这个列表可能是空的)。也就是说除了根框架,所有frame都有父。

根框架获取方法:QTextDocument::rootFrame()

注意事项:插入一个框架后,光标就在这个框架里面,再进行操作就必须重置光标位置,到这个框架的后面去,不然会出现这种情况:

(代码地址https://github.com/zzzcb/qt/commit/c315df70689bc55193ca0de0783bd5356c305a07#diff-ffd4b1d3349d0eb2c42f7240386e34bc9caaded91547c37a59499ccdbecc3b8d

还不太会用github,进去主页右上角搜索框,先输入一个 /  再输入你想搜索的主题如QTextFrame回车   这里摘抄了部分代码)

代码如下:

QTextFrameFormat fmt;
    fmt.setBackground(Qt::green);
    fmt.setMargin(1);
    fmt.setBorder(1);
    fmt.setPadding(2);
    fmt.setWidth(QTextLength(QTextLength::PercentageLength, 45));
    fmt.setPosition(QTextFrameFormat::FloatLeft);

 cursor.insertFrame(fmt);

    cursor.insertBlock();
    cursor.insertText("Showing 9 changed files with 359 additions and 0 deletions.");

QTextFrameFormat fmt2;
   fmt2.setBackground(QColor(180,142,120));
   fmt2.setMargin(1);
   fmt2.setBorder(3);
   fmt2.setPadding(2);
   fmt2.setWidth(QTextLength(QTextLength::PercentageLength, 45));
   fmt2.setPosition(QTextFrameFormat::FloatRight);
cursor.insertFrame(fmt2);

     cursor.insertBlock();
     cursor.insertText("Showing 9 changed files with 359 additions and 0 deletions.");

 所以,更正方法,是在设定第二个frameFormat  fm2前面,添加两行代码

QTextFrame *myroot=doc->rootFrame();
cursor=myroot->lastCursorPosition();

然后就由框架相互嵌套,变成平等关系:

 

4.1 QTextFrame::iterator   class

一个框架中至少包含一个块 block ,可能还有子框架。所以框架的迭代器可能找到的是一个文本块,也可能是框架,加入判断条件后,就可以进行下一步操作。迭代器找到的第一个元素是begin(),最后一个元素是 end().(注意,迭代器是只读的,不能改变任何内容)。

迭代器的一些重要方法:

 QTextBlock  currentBlock() const
 QTextFrame * currentFrame() const
 QTextFrame * parentFrame() const

案例: 

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //the whole size
    resize(900,700);

    //CSDN
    QTextEdit *editor = new QTextEdit(this);


    //my change it bigger 设置自己的偏好字体
    editor->resize(850,650);
    QTextDocument *doc = editor->document();  //获取文本文档
    QFont myfont("Bahnschrift",14);
    doc->setDefaultFont(myfont);
    QTextCursor cursor(editor->textCursor());


        cursor.insertBlock();

        //首次定义文本字符格式 charFormat变量
            QTextCharFormat chf;

        //第四次定义 然后插入新片段
        chf.setBackground(QColor(100,190,200));
        cursor.setCharFormat(chf);
        cursor.insertText("this is QTextFragment hello world hello worldhello worldhello worldhello worldhello world");
        QString str222=cursor.selectedText();


    QTextDocumentFragment  docfrag2= QTextDocumentFragment ::fromHtml("<h2>this is QTextDocumentFragment  HTML 5 new attributes </h2>");

        cursor.insertFragment(docfrag2);


    QTextFrameFormat fmt;
            fmt.setBackground(Qt::green);
            fmt.setMargin(1);
            fmt.setBorder(1);
            fmt.setPadding(2);
            fmt.setWidth(QTextLength(QTextLength::PercentageLength, 45));
            fmt.setPosition(QTextFrameFormat::FloatLeft);

            cursor.insertFrame(fmt);
            cursor.insertBlock();//这句话有没有都行,不影响打印结果
            cursor.insertText("We've combined the power of the Following feed with the For you feed so there’s one ");

            //其实默认就是这句话 所以要改,不能让新框架在旧框架里面
            //cursor=frame1->lastCursorPosition();


            QTextFrame *myroot=doc->rootFrame();
            cursor=myroot->lastCursorPosition();


        QTextFrameFormat fmt2;
            fmt2.setBackground(QColor(180,142,120));
            fmt2.setMargin(1);
            fmt2.setBorder(3);
            fmt2.setPadding(2);
            fmt2.setWidth(QTextLength(QTextLength::PercentageLength, 45));
            fmt2.setPosition(QTextFrameFormat::FloatRight);

            cursor.insertFrame(fmt2);

            cursor.insertBlock();//这句话有没有都行,不影响打印结果
            cursor.insertText("Showing 9 changed files with 359 additions and 0 deletions.");


    //自己改写,从根框架开始便利
    for (QTextFrame::iterator it = myroot->begin(); !(it.atEnd()); it++){
        QTextBlock curBlock = it.currentBlock();
        QTextFrame * curFrame = it.currentFrame();
        if (curBlock.isValid() && !(curBlock.text().isEmpty())){
            qDebug()<<"根框架的内部找到的文本块";
            qDebug()<< curBlock.text();
        }
        else if (curFrame){
             qDebug()<<"find a frame ";
            for (QTextFrame::iterator it2 = curFrame->begin(); !(it2.atEnd()); it2++){
                QTextBlock grandcBlock = it2.currentBlock();
                QTextFrame * grandcFrame = it2.currentFrame();

                if (grandcBlock.isValid() && (!grandcBlock.text().isEmpty())){
                    qDebug()<<"this is grandBLOCK in child frame ";
                    qDebug()<< grandcBlock.text();
                }
                else if(grandcFrame){
                    qDebug() <<"this is GrandFrame  in child frame " ;
                }

            }

        }
    }
}

Widget::~Widget()
{
    delete ui;
}

效果

打印结果:

根框架的内部找到的文本块
"this is QTextFragment hello world hello worldhello worldhello worldhello worldhello worldthis is QTextDocumentFragment HTML 5 new attributes "
find a frame 
this is grandBLOCK in child frame 
"We've combined the power of the Following feed with the For you feed so there’s one "
find a frame 
this is grandBLOCK in child frame 
"Showing 9 changed files with 359 additions and 0 deletions."

综上,qtextFragment 和qtextDocumentFragment 会被认为是一个整块,(反正一个单独的片段是不会被当做一个完整block的 ),然后找到了绿色的frame ,又在里面找到了子块,最后找到咖啡色frame, 在里面又发现子块。

4.2   QTextFrameFormat class

描述框架格式的类。 

注意这两个方法都可以使用,第二个更方便

[protected] void QTextObject::setFormat(const QTextFormat &format)

void QTextFrame::setFrameFormat(const QTextFrameFormat &format) 

4.3 QTextTable --表格。是 QTextFrame的子类。

不放图片了。首先将鼠标移动到 文档的最前面,在后面插入表格,表格的背景容易和大小不匹配。

 cursor.movePosition(QTextCursor::Start);



        QTextTableFormat mytablef;
        mytablef.setBorderCollapse(false);

        QBrush tablebrush(QColor(110,190,220));

       // mytablef.setHeight(60);
       // mytablef.setWidth(200);
        //写浮点数,固定了大小。但是容易跟背景出现距离上的偏差。
        mytablef.setWidth(QTextLength(QTextLength::PercentageLength,45));
        mytablef.setHeight(QTextLength(QTextLength::PercentageLength,20));

        mytablef.setHeaderRowCount(1);
        mytablef.setBackground(tablebrush);


    QTextTable *mytable = cursor.insertTable(3,3,mytablef);

    //更改单个单元格的格式,注意 从0开始数,第0行第0列是我们看起来第一个单元格。
    QTextTableCell cell = mytable->cellAt(1, 1);

    //注意,单元格的setFormat设置的是字符格式charFormat 也就是填写到这个单元格的字体格式。

    QTextCharFormat format = cell.format();

    format.setBackground(Qt::blue);
    cell.setFormat(format);
    
    

        //输入几个字,发现单元格的宽度会跟着你输入的字而变化。
        //这个目前还没找到办法

4.3.1 QTextTableFormat Class

代码如上。

4.3.2    QTextTableCell Class  

单元格类代表某个单元格的一些特性。例如所在的行(int )  ,所在的列 ( int ) ,单元格的字符格式charFormat , 背景颜色等等。

4.3.3  QTextTableCellFormat Class

5.QTextList 

5.1  QTextListFormat

6.总结  

6.1 文档元素之间的关系

QTextDocument. 

QTextBlock ,

QTextFragment, 

 QTextDocumentFragment     ,

       QTextframe ,

QTextFragment是 块的片段,但是里面能装的东西和块一样,里面能包含text文本,表格,列表,图片。

6.2  迭代器有哪些种类,各有什么用途

QTextDocument:: iterator 找到的只有block ,  it.begin() 是第一个块,it.end() 是最后一个块

QTextFrame:: iterator   能找到框架内的子块,也能找到子框架。

QTextBlock::iterator  找到的是QTextFragment  

以下代码摘抄自 

【Qt】富文本框架(一、富文本文档)_qt富文本控件_卡钦斯基的博客-CSDN博客

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

7. 其他相关的类

7.1 QTextLength

7.2 QFontMetrics

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值