QTextEdit将多个字符作为一个整体,不可单独修改

2024-05-27 09:44

本文主要是介绍QTextEdit将多个字符作为一个整体,不可单独修改,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

考虑一个问题,QTextEdit如何实现类似微信和QQ聊天输入框中的“@xxx”效果,其内容作为一个整体,以突出颜色显示,并且不可以单独编辑修改,只能整体删除修改。

突出颜色显示有很多方式可以实现,例如

  • 通过setTextColor接口,此接口可以设置当前字体颜色为指定颜色
//保存当前颜色
QColor _color = this->textColor();
//设置为红色
this->setTextColor(Qt::red);
//添加文字
this->append("hello world");
//恢复颜色
this->setTextColor(_color);
  • 通过html格式实现
this->append("<font color=\"#FF0000\">红色字体</font> ");
  • 通过QTextCharFormat实现
auto cursor = this->textCursor();
//备份格式auto backFormat = cursor.charFormat();//设置字体auto _font_size = this->font().pointSize();//构建格式QTextCharFormat _format;//设置文本颜色_format.setForeground(Qt::red);cursor.insertText(QString(QChar::ObjectReplacementCharacter),_format);//恢复默认格式this->setCurrentCharFormat(backFormat);

颜色搞定了,如何将指定的字符串设为整体呢?
通过面向百度编程和查阅文档(主要是面向百度编程,哈哈)找到一种方法。
众所周知,QTextEdit中的内容是有QTextDocument类实现渲染的,而QTextDocument的布局方式是由QAbstractTextDocumentLayout实现的,可以通过QAbstractTextDocumentLayout *QTextDocument::documentLayout()接口获取。而在QAbstractTextDocumentLayout类中提供了
void registerHandler(int objectType, QObject *component)接口可以注册自定义的Handler实现自定义绘制。因此可以通过此方式实现将多个文本作为整体。

先看效果
在这里插入图片描述
继承QTextObjectInterface实现intrinsicSizedrawObject

enum TextFormatRole
{//字体大小Format_FontSize = QTextFormat::UserProperty + 1,//文本Format_Text
};
class TextEditHander : public QObject,QTextObjectInterface
{Q_OBJECTQ_INTERFACES(QTextObjectInterface)
public:TextEditHander(QObject* parent = nullptr);~TextEditHander();//计算绘制区域QSizeF intrinsicSize(QTextDocument *doc, int posInDocument,const QTextFormat &format) override;void drawObject(QPainter *painter, const QRectF &rect, QTextDocument *doc,int posInDocument, const QTextFormat &format) override;};
TextEditHander::TextEditHander(QObject *parent):QObject(parent)
{}TextEditHander::~TextEditHander()
{}//计算绘制区域
QSizeF TextEditHander::intrinsicSize(QTextDocument *doc, int posInDocument,const QTextFormat &format)
{//获取字体大小int font_size = format.property(Format_FontSize).toInt();QString text = format.property(TextFormatRole::Format_Text).toString();auto _font = doc->defaultFont();_font.setPointSize(font_size);QFontMetrics _metrics(_font);int textWidth = _metrics.horizontalAdvance(text);return QSizeF(textWidth,_metrics.height());
}//绘制
void TextEditHander::drawObject(QPainter *painter, const QRectF &rect,QTextDocument *doc, int posInDocument, const QTextFormat &format)
{Q_UNUSED(doc);Q_UNUSED(posInDocument);QString text = format.property(Format_Text).toString();int font_size = format.property(Format_FontSize).toInt();//调整rect
//    QRectF _drawRect = rect.adjusted(0,1,0,-1);QRectF _drawRect = rect;//绘制painter->save();//绘制背景painter->fillRect(_drawRect,format.background());//绘制文字auto _font = doc->defaultFont();_font.setPointSize(font_size);painter->setFont(_font);painter->setPen(format.foreground().color());painter->drawText(_drawRect,Qt::AlignBaseline,text);painter->restore();
}

继承QTextEdit

class TextEdit : public QTextEdit
{Q_OBJECT
public:explicit TextEdit(QWidget *parent = nullptr);virtual ~TextEdit() = default;
protected slots://插入标签void slot_addText();
};
TextEdit::TextEdit(QWidget *parent): QTextEdit{parent}
{//注册handlerauto handler = new TextEditHander(this);this->document()->documentLayout()->registerHandler(QTextFormat::UserObject+1,handler);QFont _font = this->font();_font.setPointSize(12);this->setFont(_font);//创建右键菜单QAction *act = new QAction("插入标签",this);connect(act,&QAction::triggered,this,&TextEdit::slot_addText);this->addAction(act);this->setContextMenuPolicy(Qt::ActionsContextMenu);
}void TextEdit::slot_addText()
{auto cursor = this->textCursor();//备份格式auto backFormat = cursor.charFormat();//设置字体auto _font_size = this->font().pointSize();//构建格式QTextCharFormat _format;//设置格式使用自定义的Hander渲染,这步很重要_format.setObjectType(QTextFormat::UserObject + 1);//设置需要绘制的文本_format.setProperty(TextFormatRole::Format_Text,"${123}");//设置字体大小_format.setProperty(TextFormatRole::Format_FontSize,_font_size);//设置前景色_format.setForeground(Qt::black);//设置背景色_format.setBackground(Qt::lightGray);cursor.insertText(QString(QChar::ObjectReplacementCharacter),_format);//恢复默认格式this->setCurrentCharFormat(backFormat);//添加一个空格this->textCursor().insertText(" ");}

这篇关于QTextEdit将多个字符作为一个整体,不可单独修改的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1007127

相关文章

mybatis的整体架构

mybatis的整体架构分为三层: 1.基础支持层 该层包括:数据源模块、事务管理模块、缓存模块、Binding模块、反射模块、类型转换模块、日志模块、资源加载模块、解析器模块 2.核心处理层 该层包括:配置解析、参数映射、SQL解析、SQL执行、结果集映射、插件 3.接口层 该层包括:SqlSession 基础支持层 该层保护mybatis的基础模块,它们为核心处理层提供了良好的支撑。

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚:

如何在运行时修改serialVersionUID

优质博文:IT-BLOG-CN 问题 我正在使用第三方库连接到外部系统,一切运行正常,但突然出现序列化错误 java.io.InvalidClassException: com.essbase.api.base.EssException; local class incompatible: stream classdesc serialVersionUID = 90314637791991

android系统源码12 修改默认桌面壁纸--SRO方式

1、aosp12修改默认桌面壁纸 代码路径 :frameworks\base\core\res\res\drawable-nodpi 替换成自己的图片即可,不过需要覆盖所有目录下的图片。 由于是静态修改,则需要make一下,重新编译。 2、方法二Overlay方式 由于上述方法有很大缺点,修改多了之后容易遗忘自己修改哪些文件,为此我们采用另外一种方法,使用Overlay方式。

string字符会调用new分配堆内存吗

gcc的string默认大小是32个字节,字符串小于等于15直接保存在栈上,超过之后才会使用new分配。

如何将一个文件里不包含某个字符的行输出到另一个文件?

第一种: grep -v 'string' filename > newfilenamegrep -v 'string' filename >> newfilename 第二种: sed -n '/string/!'p filename > newfilenamesed -n '/string/!'p filename >> newfilename

MySQL脏读、不可重复读、幻读(虚读)

事务的特性: 原子性:指处于同一个事务中的多条语句是不可分割的。一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。比如转账,转账前两个账户余额之和为2k,转账之后也应该是2K。隔离性:指多线程环境下,一个线程中的事务不能被其他线程中的事务打扰持久性:事务一旦提交,就应该被永久保存起来。 事务隔离性问题: 如果不考虑事务的隔离性,会出现以下问题: 脏读:指一个线程中的事务读取到

struts2中的json返回指定的多个参数

要返回指定的多个参数,就必须在struts.xml中的配置如下: <action name="goodsType_*" class="goodsTypeAction" method="{1}"> <!-- 查询商品类别信息==分页 --> <result type="json" name="goodsType_findPgae"> <!--在这一行进行指定,其中lis是一个List集合,但

hibernate修改数据库已有的对象【简化操作】

陈科肇 直接上代码: /*** 更新新的数据并并未修改旧的数据* @param oldEntity 数据库存在的实体* @param newEntity 更改后的实体* @throws IllegalAccessException * @throws IllegalArgumentException */public void updateNew(T oldEntity,T newEntity

一款支持同一个屏幕界面同时播放多个视频的视频播放软件

GridPlayer 是一款基于 VLC 的免费开源跨平台多视频同步播放工具,支持在一块屏幕上同时播放多个视频。其主要功能包括: 多视频播放:用户可以在一个窗口中同时播放任意数量的视频,数量仅受硬件性能限制。支持多种格式和流媒体:GridPlayer 支持所有由 VLC 支持的视频格式以及流媒体 URL(如 m3u8 链接)。自定义网格布局:用户可以配置播放器的网格布局,以适应不同的观看需求。硬