zoukankan      html  css  js  c++  java
  • QTextEdit 总结

    关于Qt的富文本处理, 可以参考文档: Rich Text Processing

    该文档有人翻译了一下(本来我想翻译- -!), 参考Rich Text Processing富文本处理 

    QTextEdit的组成比较复杂, 最好看看文档了解一下Rich Text Document Structure

    1. HTML形式操纵Qtextedit

      QTextEdit支持HTML的一个子集, 所以对于简单的使用, 可以直接插入HTML代码

      

    editor->append("<img src="mydata://image.png" />");

      通过插入html代码, 可以实现图片, 字体, 字号, 颜色等功能
     ps: QTextEdit中img标签仅支持src, width, height三个属性, 使用其他属性会自动被Qt过滤掉, 即editor->toHtml()中无法找到

      可以通过正则来过滤toHtml()生成的代码

      其他HTML支持, 参考Supported HTML Subset

    2. 在QTextEdit中播放gif

      QTextEdit虽然直接img标签, 但默认不播放gif, 也不会显示gif的第一帧 (如果你不需要编辑功能的话, 其实可以用QWebView来查看)

      所以在QTextEdit中播放gif需要手动换帧. 

      QMovie内置了gif解析和定时器功能. 

      QTextDocument 使用addResource 把图片资源加载进来, 然后通过QMovie->start启动定时器, 不断更新图片资源

    QString g_fileName = ":/test.gif";
    QUrl g_url("TestImageTag"); 
    void MyClass::InsertImage()
    {
        QMovie* movie = new QMovie(this); 
        movie->setFileName(g_fileName);  
        movie->setCacheMode(QMovie::CacheNone);  
    
        //换帧时刷新  
        connect(movie, SIGNAL(frameChanged(int)), this, SLOT(OnAnimate(int)));  
        movie->start(); 
    }

    g_url 是自定义的标签, 用来标记QTextDocument 中的resource

    void MyClass::OnAnimate(int a)  
    {  
        if (QMovie* movie = qobject_cast<QMovie*>(sender()))  
        {              
            document()->addResource(QTextDocument::ImageResource,   //替换图片为当前帧  
                                    g_url, movie->currentPixmap());     
              
            setLineWrapColumnOrWidth(lineWrapColumnOrWidth()); // 刷新显示  
        }  
    }  

    addResource 指定ImageResource, 然后根据url, 若url已存在, 则更新资源, 若url不存在, 则添加资源

    这样就实现刷新gif的帧. 这样, QTextEdit就会显示gif动画了

    最后是添加gif图片:

    可以插入HTML: 

    editor->append("<img src="TestImageTag" />");

    即img中指定为我们自定义的url即可

    也可以使用QTextCursor插入:

    QTextCursor cursor = editor->textCursor(); 
    QTextImageFormat imageFormat;
    imageFormat.setName("TestImageTag");
    cursor.insertImage(imageFormat);

    PS: 可以使用两个数组来保存自定义的URL和QMOVIE, 以便管理资源释放等问题

    PS2: 在我的测试中, 即使调用了Qtextedit和QTextDocument的clear也无法释放addResource图片资源的内存.  只有把QTextEdit整个delete掉, 才会释放所有图片资源占据的内存.  这是个问题, 可能需要看源码来解决. 不过如果图片不多的话, 这个问题也可以忽略

    3. 如何遍历QTextEdit中的内容

      QTextEdit中的内容实际上是由QTextDocument维护

      可以简单的理解: QTextDocument 包含 N个QTexBlock(段落), 每个QTexBlock包含N个QTextFragment

      

    QColor _GetRamdomColor()
    {
        QColor col; 
        int RamdomNum = rand() % 0xffffff; 
        char strCol[8];
        sprintf(strCol, "#%06x", RamdomNum);     
        col.setNamedColor(QString::fromLocal8Bit(strCol, 8)); 
        return col; 
    }
    
    
    void MyClass::OnTest()
    {
        QTextDocument *document = ui.textEdit->document(); 
        QTextBlock &currentBlock = document->begin();
        QTextBlock::iterator it;
        QTextCursor cursor = ui.textEdit->textCursor(); 
    
        while( true)
        {
            // 在修改chatformat时会改变当前Block的fragment
            // 所以++it的处理类似std::map中的erase操作
            for (it = currentBlock.begin(); !(it.atEnd()); )
            {
                QTextFragment currentFragment = it.fragment();
                QTextImageFormat newImageFormat = currentFragment.charFormat().toImageFormat();
    
                if (newImageFormat.isValid()) {
                    // 判断出这个fragment为image
                    ++it; 
                    continue;
                }
    
    
                if (currentFragment.isValid())
                {
                    ++it; 
                    int pos = currentFragment.position();
                    QString strText = currentFragment.text();
                    for(int i = 0; i < strText.length(); i++)
                    {    
                        // 选择一个字, 随机设定颜色
                        QTextCharFormat fmt;
                        fmt.setForeground(_GetRamdomColor());                    
                        QTextCursor helper = cursor;
                        helper.setPosition(pos++);
                        helper.setPosition(pos, QTextCursor::KeepAnchor);
                        helper.setCharFormat(fmt);
                    }                
                }
    
            }
    
            currentBlock = currentBlock.next();
            if(!currentBlock.isValid())
                break;
        }
        // 光标移动到最后, 并设置拥有焦点
        QTextCursor c = ui.textEdit->textCursor();
        c.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); 
        ui.textEdit->setTextCursor(c);    
        ui.textEdit->setFocus(Qt::MouseFocusReason);
    }

    这段代码用于渲染QTextEdit为炫彩, 每个字随机分配一种颜色

    遍历的时候, 判断是图片还是文字. 并作相应的处理

    同时, 处理下QTextDocument的contentChange事件, 即可在键盘输入时, 就改变字的颜色

        connect(document, SIGNAL(contentsChange( int , int , int )), 
            this, SLOT(OnContentChange( int , int , int )));
    void MyClass::OnContentChange( int position, int charsRemoved, int charsAdded )
    {
        if(charsAdded == 0)
            return;
    
        QTextCursor cursor = ui.textEdit->textCursor(); 
        for (int i = 0; i < charsAdded; i++ )
        {
            int pos = position + i; 
            // 选择一个字, 随机设定颜色
            QTextCharFormat fmt;
            fmt.setForeground(_GetRamdomColor());
            QTextCursor helper = cursor;
            helper.setPosition(pos);
            helper.setPosition(pos+1, QTextCursor::KeepAnchor);
            helper.setCharFormat(fmt);
        }
    
    }

    PS: 对某段文字执行setCharFormat也会触发contentChange信号, 并且charsRemoved == charsAdded; 可以处理一下这个case

      这样一般来说满足了大部分需求, 做出类似QQ的聊天输入框只需要再处理下复制黏贴图片之类就行了. 至于Qt的rich edit中frame table list等, 需要的话, 就看看文档吧, 感觉功能不是很必要
  • 相关阅读:
    第四周作业
    第三周作业
    第二周作业
    互联网公司采用增量模型做开发的优势
    面向过程分析方法与面向对象分析方法到底区别
    项目测试中的黑盒测试和白盒测试
    立项说明书里面的项目概述。
    项目开发中的一些问题
    面向对象之我见
    [自翻]fasthttp中文文档(持续更新)
  • 原文地址:https://www.cnblogs.com/lingdhox/p/3393207.html
Copyright © 2011-2022 走看看