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

news2024/9/25 20:41:17

考虑一个问题,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_OBJECT
    Q_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}
{
    //注册handler
    auto 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(" ");

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1700932.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

echarts- 热力图, k线图,雷达图

热力图 热力图可以看成是一种矩形的散点图。 热力图的矩形受itemStyle的影响。 通常配合visualmap组件来根据值的大小做颜色的变化。 热力图主要通过颜色去表现数值的大小&#xff0c;必须要配合 visualMap 组件使用。 visualMap:视觉映射组件 let options {tooltip: {},xAx…

【全开源】景区手绘地图导览系统源码(ThinkPHP+FastAdmin)

一款基于ThinkPHPFastAdmin开发多地图手绘地图导览系统(仅支持H5)&#xff0c;景区升4A5A必备系统&#xff0c;高级版支持全景。 ​打造个性化游览新体验 一、引言&#xff1a;景区导览系统的革新 在旅游业蓬勃发展的今天&#xff0c;景区导览系统成为了提升游客体验的关键。…

如何获取某个城市或区域的人口分布数据?

人口分布数据在多个领域都扮演着至关重要的角色。这些数据不仅反映了一个国家或地区的人口分布状况&#xff0c;而且为政策制定者、企业决策者和研究者提供了宝贵的信息。那么&#xff0c;我们如何获取这些重要的人口分布数据呢&#xff1f; 政府统计部门是最主要的来源。各国政…

MybatisPlusGenerator交互式Web生成增删改查、导出导入代码

个人博客&#xff1a;无奈何杨&#xff08;wnhyang&#xff09; 个人语雀&#xff1a;wnhyang 共享语雀&#xff1a;在线知识共享 Github&#xff1a;wnhyang - Overview 简介 前有文章MybatisPlus-Generator自定义模版生成CRUD、DTO、VO、Convert等介绍如何使用MybatisPlu…

翻译《The Old New Thing》- Why are INI files deprecated in favor of the registry?

Why are INI files deprecated in favor of the registry? - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20071126-00/?p24383 Raymond Chen 2007年11月26日 为什么弃用 INI 文件而改用注册表&#xff1f; 欢迎&#xff0c;Slashdot的读…

JVM学习-垃圾回收器(一)

垃圾回收器 按线程数分类 串行垃圾回收器 串行回收是在同一时间段内只允许有一个CPU用于执行垃圾回收操作&#xff0c;此时工作线程被暂停&#xff0c;直至垃圾收集工作结束 在诸如单CPU处理器或者较小的应用内存等硬件平台不是特别优越的场合&#xff0c;串行回收器的性能表…

html5+css3+js学习记录(1)-- html

1 vscode前端插件 1.1 Web标准 2 文档声明与字符编码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewpor…

一文教你如何调用Ascend C算子

Ascend C是CANN针对算子开发场景推出的编程语言&#xff0c;原生支持C和C标准规范&#xff0c;兼具开发效率和运行性能。基于Ascend C编写的算子程序&#xff0c;通过编译器编译和运行时调度&#xff0c;运行在昇腾AI处理器上。使用Ascend C&#xff0c;开发者可以基于昇腾AI硬…

【全开源】排队叫号系统源码(FastAdmin+GatewayWorker)

一款基于FastAdminGatewayWorker开发的多项目多场景排队叫号系统&#xff0c;支持大屏幕投屏&#xff0c;语音播报叫号&#xff0c;可用于餐厅排队取餐、美甲店排队取号、排队领取、排队就诊、排队办理业务等诸多场景&#xff0c;助你轻松应对各种排队取号叫号场景。 ​打造高…

Java中的JSON神器,如何轻松玩转复杂数据结构

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 一、揭秘JSON世界的基石 在Java的世界中&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;它基于文本&#xff0c;易于阅读和编写&#xff0c;同时也易于…

易备数据备份软件:快速恢复 VMware ESXi 虚拟机

易备数据备份软件为 VMware ESXi 虚拟机提供完整的保护和备份功能。软件同时支持从 ESXi 或 vCenter 虚拟机的增量和差异备份中进行自动恢复。支持精细化的恢复&#xff0c;可将虚拟机恢复到某个特定的日期。 通过易备数据备份软件&#xff0c;可以实现虚拟机的异机恢复&#…

SuperSocket 协议

1、通过之前的学习&#xff0c;我们知道在SuperSocket中&#xff0c;客户端向服务器发送数据时需要以回车换行符“\r\n”结尾服务端才能够识别。这是因为SuperSocket的默认协议CommandLineProtocol&#xff08;命令行协议&#xff09;要求所致。SuperSocket还有以下常用的协议&…

事务报错没有显示回滚导致DDL阻塞引发的问题

在业务开发过程中&#xff0c;显示的开启事务并且在事务处理过程中对不同的情况进行显示的COMMIT或ROLLBACK&#xff0c;这是一个完整数据库事务处理的闭环过程。 这种在应用开发逻辑层面去handle的事务执行的结果&#xff0c;既确保了事务操作的数据完整性&#xff0c;又遵循了…

ROS2入门21讲__第21讲__ROS2应用与进阶攻略

资源汇总 常用框架 自主导航 比如移动机器人基本都会具备的自主导航功能&#xff0c;ROS2提供了完整的自主导航系统框架和各种实现好的算法&#xff0c;即便我们不开发任何代码&#xff0c;也可以在自己的机器人上&#xff0c;使用这套系统&#xff0c;快速实现自主导航的基本…

X-CSV-Reader:一个使用Rust实现CSV命令行读取器

&#x1f388;效果演示 ⚡️快速上手 依赖导入&#xff1a; cargo add csv读取实现&#xff1a; use std::error::Error; use std::fs::File; use std::path::Path;fn read_csv<P: AsRef<Path>>(filename: P) -> Result<(), Box<dyn Error>> {le…

40岁的戴尔在AI时代翻红了

戴尔公司股价创历史新高&#xff0c;市值达1138亿美元&#xff0c;涨幅110%。戴尔向AI押注多年&#xff0c;收购企业转型&#xff0c;成为数据基础设施厂商。AI服务器销售增长&#xff0c;分析师看好戴尔未来发展。 5月24日美股收盘&#xff0c;很多人可能不太关注的戴尔公司股…

华为OD机试【计算最接近的数】(java)(100分)

1、题目描述 给定一个数组X和正整数K&#xff0c;请找出使表达式X[i] - X[i1] … - X[i K 1]&#xff0c;结果最接近于数组中位数的下标i&#xff0c;如果有多个i满足条件&#xff0c;请返回最大的i。 其中&#xff0c;数组中位数&#xff1a;长度为N的数组&#xff0c;按照元…

MP3文件本地存储与下载指南

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言 二、建立存储文件夹 三、获取MP3文件URL并下载 四、优化下载过程 五、总结与…

韩愈,文起八代之衰的儒学巨匠

&#x1f4a1; 如果想阅读最新的文章&#xff0c;或者有技术问题需要交流和沟通&#xff0c;可搜索并关注微信公众号“希望睿智”。 韩愈&#xff0c;字退之&#xff0c;生于唐代宗大历三年&#xff08;公元768年&#xff09;&#xff0c;卒于唐穆宗长庆四年&#xff08;公元82…

Activiti7_使用

Activiti7_使用 一、Activiti7二、绘制工作流三、通过代码部署流程&#xff0c;再对流程进行实例化&#xff0c;完整运行一遍流程即可四、在springbooot中使用 一、Activiti7 为了实现后端的咨询流转功能&#xff0c;学习Activiti7&#xff0c;记录下使用的过程及遇到的问题 二…