关于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[];
sprintf(strCol, "#%06x", RamdomNum);
col.setNamedColor(QString::fromLocal8Bit(strCol, ));
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 = ; 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 == )
return; QTextCursor cursor = ui.textEdit->textCursor();
for (int i = ; i < charsAdded; i++ )
{
int pos = position + i;
// 选择一个字, 随机设定颜色
QTextCharFormat fmt;
fmt.setForeground(_GetRamdomColor());
QTextCursor helper = cursor;
helper.setPosition(pos);
helper.setPosition(pos+, QTextCursor::KeepAnchor);
helper.setCharFormat(fmt);
} }
PS: 对某段文字执行setCharFormat也会触发contentChange信号, 并且charsRemoved == charsAdded; 可以处理一下这个case

  这样一般来说满足了大部分需求, 做出类似QQ的聊天输入框只需要再处理下复制黏贴图片之类就行了. 至于Qt的rich edit中frame table list等, 需要的话, 就看看文档吧, 感觉功能不是很必要

QTextEdit 总结的更多相关文章

  1. QTextEdit中选中文本修改字体与颜色,全部文本修改字体与颜色(设置调色板的前景色、背景色、文字颜色以及基色)

    ----我的生活,我的点点滴滴!! 当然以下内容都可以通过设置样式来达到目的,但是下面不使用这样的方法 先来看张图,理解此图基本就能实现上面所要达到的目的了 Widget::Widget(QWidge ...

  2. QTextEdit控件使用

    QTextEdit控件使用 QTextEdit *mpContentTextEdit = new QTextEdit(this); //设置占位符文本 mpContentTextEdit->se ...

  3. 2.QLabel,QPushButton,QLineEdit,QComboBox,QCheckBox,QRadioButton,QTextEdit,QTextBrowser,QGroupBox,QSl

     1.新建一个空项目(其它项目->空QT项目): 2  添加新文件(选择C++Class) MyWidget.h #ifndef MYWIDGET_H #define MYWIDGET_H ...

  4. QT—QTextEdit控件显示日志

    功能:利用QTextEdit开发一个日志显示窗口.没有太多操作,需要实现的是日志自动向上滚动,总体的日志量可以控制在x行(比如300行)以内:其他的应用功能我后面继续添加 #include <Q ...

  5. 文本编辑框QTextEdit

    QTextEdit类是一个多行文本框控件,可以显示多行文本内容,当文本内容超出控件显示范围时,可以显示水平个垂直滚动条,Qtextedit不仅可以用来显示文本还可以用来显示HTML文档 import ...

  6. Qt QTextEdit根据行号移动光标

    QTextEdit* p = new QTextEdit; QTextBlock block = p->document()->findBlockByNumber(nLineNum); p ...

  7. qt中qlineedit和qtextedit右键菜单翻译成中文

    没有linguist和lupdate等命令需要安装Linguist: 在Terminal中输入: sudo apt-get install qt4-dev-tools qt4-doc qt4-qtco ...

  8. 【Qt开发】QTextEdit 外观属性设置

    一.给QTextEdit添加背景图片,有下面两种方法: QTextEdit* iEdit  = new QTextEdit(); 1:使用样式表: iEdit->setStyleSheet(&q ...

  9. GUI学习之十二——QTextEdit学习总结

    在学习了QFrame和QAbstractScrollArea两个父类后,接下来是一个重头戏:QTextEdit. 一.QTextEdit特性 QTextEdit是一个高级的WYSIWYG(What Y ...

随机推荐

  1. 大话细说ORM

    什么是ORM? ORM,即对象关系映射(Object Relational Mapping)表示一种技术,用来把(对象模型)表示的对象映射到基于SQL的(关系模型)数据结构中去. 说得通俗点,就是在对 ...

  2. ini_set /ini_get函数功能-----PHP

    配置PHP环境时,我们记得最初的一步就是修改php.ini文件,但是当我们在虚拟机中运行脚本,或者是我们因为其他的原因没有修改php.ini的权限时,我们该怎么办? ini_set()函数提供了在脚本 ...

  3. Ubuntu 12.04 中安装ubuntu-tweak出错

    错误信息: ubuntu-tweakE: Sub-process /usr/bin/dpkg returned an error code (1) 解决办法: 第一步:删除 /usr/share/py ...

  4. ArcMap10.1修改要素属性字段

    ArcMap10.1修改要素属性字段 问题描述:在ArcMap10.1中编辑要素属性表时,遇到输入字段值的长度超过字段最大长度时,ArcMap会抛出“基础DBMS错误[ORA-12899:value ...

  5. Namespaces(命名空间)

    datastore,Blobstore,memcache一起为应用存储数据.这对于在全球范围内分割数据是有用的.比如,一个应用可以为多个公司服务,每个公司可以看到它自己的隔离的应用实例,没有公司可以看 ...

  6. HDU4864:Task(贪心)

    题意: 给出n个机器和m个任务,对于一天来说,每个机器有最大工作时间xi,可接受最大等级yi,每个任务有一个工作时间xi,一个等级yi,可获价值为500*xi+2*yi,任务需要在一台机器一天内完成, ...

  7. 【bzoj3233】【ahoi2013】找硬币

    题意: 求确定n种货币面额x1..xn满足 x1=1 且xi为xj的整数倍(i>j) 给定n个物品价格ai 求使用上面货币最少需要硬币数(不能找零) 题解: 动态规划 听说网上的题解都是搜索的做 ...

  8. Stunnix C++ Obfuscator使用简介

    因为项目的需求,需要混淆C代码.目前.net和java混淆工具很好用.但是c混淆工具不多.找到一个Stunnix C++ Obfuscator http://www.stunnix.com/网上很少有 ...

  9. Spark Streaming 原理剖析

    通过源码呈现 Spark Streaming 的底层机制. 1. 初始化与接收数据 Spark Streaming 通过分布在各个节点上的接收器,缓存接收到的流数据,并将流数 据 包 装 成 Spar ...

  10. 在C++中定义常量的两种方法的比较

    常量是定以后,在程序运行中不能被改变的标识符.C++中定义常量可以用#define .const 这两种方法.例如:#define PRICE 10 //定义单价常量10const int PRICE ...