Qt解析含颜色的QString字符串显示到控件

news2024/11/19 2:20:20

1、需求

开发接收含颜色字符串显示到窗口,可解析字符串颜色配置窗口属性,且分割字符串显示。
mprintf(“xxxxxx”);打印的xxxxxx含有颜色配置。

2、实现方法

2.1、条件

选用Qt的PlainTextEdit控件显示字符串,配置为只读模式

初始化串口成功后,用下列代码绑定串口信号,收到数据会及时显示

connect(this->serialPort,SIGNAL(readyRead()),this,SLOT(log_serialread()));

/* readyRead()触发,接收到的数据长度是不定长的 */
/* log_serialread()是自己实现的接收函数 */
2.2、颜色配置函数

颜色规则参考链接: ANSI控制码

void logThread::display_config(const QString &text)
{
    QTextCharFormat fmt;
    QMap<QString, int> map; //颜色列表
    map["black"] = 30;  //背景色40
    map["red"] = 31;    //背景色41
    map["green"] = 32;  //背景色42
    map["yellow"] = 33; //背景色43
    map["blue"] = 34;   //背景色44
    map["magenta"] = 35;//背景色45
    map["cyan"] = 36;   //背景色46
    map["white"] = 37;  //背景色47

    QString text_style = text;
    QRegularExpression regex("\x1b\\["); 
    QRegularExpression regex_else("m"); 
    text_style = text_style.remove(regex); //去掉\033[
    text_style = text_style.remove(regex_else); //去掉m

    QStringList list = text_style.split(";"); //用;分割属性成列表
    foreach (QString type, list) {
        if(type == "0") { //常规文本,清除属性
            fmt.setForeground(QBrush(QColor("black")));
            fmt.setFontWeight(50); //取消加粗
            fmt.setFontUnderline(false); //取消下划线
        }
        else if(type == "1") { //加粗文本
            fmt.setFontWeight(63); //63、75、87
        }
        else if(type == "4") { //含下划线文件
            fmt.setFontUnderline(true);
        }

        if((type.toInt() >= 30) && (type.toInt() <= 47))
        {
            QMap<QString, int>::iterator itor;
            for (itor = map.begin(); itor != map.end(); ++itor)
            {
                if(type.toInt() == itor.value()) //30 ~ 37
                {
                    fmt.setForeground(QBrush(QColor(itor.key()))); //字体色
                }
                else if((type.toInt() - 10) == itor.value()) //40 ~ 47
                {
                    fmt.setBackground(QBrush(QColor(itor.key()))); //背景色
                }
            }
        }
    }

    this->printlog_displayPlainTextEdit->mergeCurrentCharFormat(fmt);
}
2.3、log显示函数
void logThread::log_display(const QString &text)
{
    QString text_in = text;
    text_in = text_in.remove(QRegularExpression("\\r")); //去掉\r,会当做换行

    #if 0
    //将获取的数据追加在文本编辑的末尾,会导致插入的文本换行,显示会乱
    this->displayPlainTextEdit->appendPlainText(text_in);
    #else
    //虽然配置为只读,如果鼠标移动了光标,会导致当前这段数据跳到光标处显示
    this->displayPlainTextEdit->insertPlainText(text_in); //当前光标位置显示
    this->displayPlainTextEdit->moveCursor(QTextCursor::End,QTextCursor::MoveAnchor); //移动光标到最后
    #endif
}
2.4、log接收函数

3种情况的处理规则如图:

在这里插入图片描述

代码实现:

void logThread::log_serialread()
{
    static QString str;
    int config_flag = 0;
    
    /* 每一次readyRead()触发,都把数据读完,长度不定长*/
    QString buf = QString(this->serialPort->readAll());
    int string_length = buf.length();
    
    if(!save_str.isEmpty()) //上一次存储的字符串不为空
    {
        buf = save_str + buf; //拼接到当前字符串前
        string_length = buf.length();
        save_str = ""; //清除存储的字符串       
    }

    QRegularExpression re_esc("\x1b"); //匹配颜色标志\033
    QRegularExpressionMatchIterator j = re_esc.globalMatch(buf); //运用迭代器,可获取每个\033的位置
    int count_esc = 0;
    int last_esc_index = 0;
    while (j.hasNext()) //是否有下一个匹配结果
    {
        count_esc++; //统计\033的个数
        QRegularExpressionMatch match = j.next();; //next()指针往后移动1
        if(!(j.hasNext())) //无下一个匹配结果,记录最后一个\033的位置
        {
            last_esc_index = match.capturedStart();
        }
    }

    QRegularExpression re("\x1b\\[[0-9;]*[mGKF]"); //匹配完整颜色配置
    QRegularExpressionMatchIterator i = re.globalMatch(buf);
    QRegularExpressionMatch match_before;
    int count = 0; 
    while (i.hasNext()) {
        config_flag = 1; //标志按照颜色配置分割字符串显示
        count++; //统计完整颜色配置的个数
        QRegularExpressionMatch match = i.next(); //next()指针往后移动1
        
        if(count == 1) //取第一个完整颜色标签之前的文字显示
        {
            if(match.capturedStart() != 0)
            {
            		//buf.left()表示从下标0往后,分割match.capturedStart()个字符
                this->log_display(buf.left(match.capturedStart()));
            }
        }
        else //取上一个标签和当前标签之间字符串显示
        {   
        		 //先按上一个标签配置颜色
            this->display_config(match_before.captured());
            //buf.mid()从下标match_before.capturedEnd()往后,分割match.capturedStart() - match_before.capturedEnd()个字符
            this->log_display(buf.mid(match_before.capturedEnd(), match.capturedStart() - match_before.capturedEnd()));
        }
     
        if(!(i.hasNext())) //无下一个匹配结果
        {
            //按当前标签配置颜色
            this->display_config(match.captured());
            if(count_esc != count) //完整颜色标签和\033个数不一样
            {
                //取当前标签和最后的\033之间字符串显示
                this->log_display(buf.mid(match.capturedEnd(), last_esc_index - match.capturedEnd()));
                
                //存储不完整颜色标签(最后\033及之后的字符串)
                save_str = buf.right(string_length - last_esc_index);
            }
            else
            {
                //取末尾标签后面的所有内容显示
                this->log_display(buf.right(string_length - match.capturedEnd()));
            }
        }
        else //有下一个匹配,存储当前的
        {
            match_before = match; 
        }
    }

    if(!config_flag)
    {
        this->log_display(buf);
    }
}
2.5、显示结果

log内容:

mprintf("\033[1;31mhello\033[0;31m\n"); //1;31m表示红色加粗,0;31m表示红色和取消加粗
mprintf("world\n");
mprintf("\033[32mhello hello\033[0m\n"); //32m表示绿色,0m表示取消颜色
mprintf("world world\n");
mprintf("\033[1;33mhello hello hello\033[0m\n"); //1;33m表示黄色加粗
mprintf("world world world\n");
mprintf("\033[34mhello hello hello hello\033[0;34m\n"); //34m表示蓝色
mprintf("world world world world\n");
mprintf("\033[35mhello hello hello hello hello\033[0;35m\n"); //35m表示紫色
mprintf("world world world world world\n");
mprintf("\033[1;36mhello hello hello hello hello hello\033[0m\n"); //36m表示青色
mprintf("world world world world world world\n");
mprintf("\033[37mhello hello hello hello hello hello hello\033[0;37m\n"); //37m表示白色
mprintf("world world world world world world world\n");

显示结果:

在这里插入图片描述

3、注意事项

“ \t ” 即table,直接送到显示,可能是默认的10多个空格,显示不是很好看,验证配置为8个空格可以对齐。

//设置制表符\t为8个空格
QFontMetrics metrics(this->printlog_displayPlainTextEdit->font());
int tabStopWidth = 8 * metrics.width(' ');
this->printlog_displayPlainTextEdit->setTabStopDistance(tabStopWidth);

“ \r ” 即为enter,直接送到显示,会换行,不需要多余的换行,可以用下列方法去掉。

QString text_in = "\r\n你好\r\n";
text_in = text_in.remove(QRegularExpression("\\r")); //去掉\r,会当做换行

new一个新的QSerialPort()前,一定要检查指针是否为空,关闭串口delete时,一定要将指针置为空,不然程序闪退。

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

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

相关文章

存内计算引领新一代技术革新,开启算力新时代

文章目录 存内计算与传统计算的区别 存内计算与传统计算的区别 存内计算芯片的优势 存内计算在各个领域的应用 存内计算技术对未来发展的影响 CSDN存内计算开发者社区&#xff1a;引领新一代技术革新的最前沿 社区内容专业度 社区具备的资源 社区的开放性 社区招募令…

网络上的诈骗:了解网络钓鱼

网络钓鱼&#xff08;Phishing&#xff09;是一种常见的网络诈骗形式&#xff0c;旨在通过假冒合法的电子通讯手段骗取个人信息、财务数据或登录凭证。 这种攻击通常涉及发送看似来自可信来源的电子邮件、短信或社交媒体消息&#xff0c;诱使受害者提供敏感信息或点击恶意链接…

前端项目部署发版流程

一、本地代码以全部提交并推送至仓库 二、项目根目录添加&#xff08;Dockerfile、nginx.conf文件&#xff09; 三、npm run build打包生成dist文件&#xff08;项目根目录&#xff09; 四、启动docker(登录状态) 五、执行命令 docker buildx build -t ‘项目的容器集群地…

【产品交互】超全面B端设计规范总结

不知不觉已经深耕在B端这个领域3年有余&#xff0c;很多人接触过B端后会觉得乏味&#xff0c;因为B端的设计在视觉上并没有C端那么有冲击力&#xff0c;更多的是结合业务逻辑&#xff0c;设计出符合业务需求的交互&#xff0c;以及界面排版的合理性&#xff0c;达到产品的可用性…

国产芯片替代趋势:发展前景与挑战全面解读

在当今数字化浪潮中&#xff0c;国产芯片替代正成为引人注目的趋势。本文将深入剖析该趋势的发展前景与挑战&#xff0c;并提供替代芯片查询的实用技巧。无论是科技从业者普通用户&#xff0c;都将在这篇文章中找到了对未来技术格局的洞察。同时&#xff0c;我们将通过上道合顺…

气象条件对铸铁平台地基深度有哪些影响呢——河北北重

气象条件对铸铁平台地基有以下影响&#xff1a; . 1.地震 地震可能导致地基的震动和错动&#xff0c;因此地震活跃区域的建筑物通常需要更深的地基以提供更大的稳定性。 2..温度变化&#xff1a;气温的变化会导致地基中的土壤膨胀和收缩&#xff0c;从而影响地基的稳定性。特…

《WebKit 技术内幕》学习之五(4): HTML解释器和DOM 模型

4 影子&#xff08;Shadow&#xff09;DOM 影子 DOM 是一个新东西&#xff0c;主要解决了一个文档中可能需要大量交互的多个 DOM 树建立和维护各自的功能边界的问题。 4.1 什么是影子 DOM 当开发这样一个用户界面的控件——这个控件可能由一些 HTML 的标签元素…

【GitHub项目推荐--人脸识别】【转载】

01 带有移动应用程序的人脸识别库 OpenFace 作为用于人脸识别的通用库&#xff0c;能够实现瞬态和移动人脸识别&#xff0c;目前在 GitHub 上斩获 14291 Star。以下为 LFW 数据集 Sylvestor Stallone 输入单个图像的流程。 项目地址&#xff1a;https://github.com/cmusatya…

新年钜惠|泰迪智能科技免费协助企业完成3个行业AI案例建模

在新年到来之际&#xff0c;为了感谢各企业一直以来对泰迪智能科技的支持&#xff0c;日前我们推出了新年钜惠活动即&#xff1a;免费协助企业完成3个行业AI案例建模。我们希望通过这样的活动&#xff0c;可以帮助更多的企业迈出AI应用的第一步&#xff0c;同时我们也希望能够为…

黑马苍穹外卖学习Day10

文章目录 Spring Task介绍cron表达式入门案例 订单状态定时处理需求分析代码开发功能测试 WebSocket介绍入门案例 来单提醒需求分析代码开发 客户催单需求分析代码开发 Spring Task 介绍 cron表达式 入门案例 订单状态定时处理 需求分析 代码开发 新建一个task包里面编写代码…

记录xxl-job重复执行引发业务问题

业务问题描述 1.创建运单&#xff0c;发现重复&#xff08;同一个车架号两条记录&#xff09; 2.通知重复反馈&#xff0c;A系统读取中间表状态为未处理数据&#xff0c;推送到B系统 原因分析 1.以上两个问题都是xxljob定时执行的 2.通过日志分析&#xff0c;读取中间表数…

【sgTree】自定义组件:加载el-tree树节点整棵树数据,实现增删改操作。

特性 可以自定义主键、配置选项支持预定义节点图标&#xff1a;folder文件夹|normal普通样式多个提示文本可以自定义支持动态接口增删改节点可以自定义根节点id可以设置最多允许添加的层级深度支持拖拽排序&#xff0c;排序过程还可以针对拖拽的节点深度进行自定义限制支持隐藏…

Find My手套|苹果Find My技术与手套结合,智能防丢,全球定位

手套是手部保暖或劳动保护用品&#xff0c;也有装饰用的。手套是个很特别的东西&#xff0c;当初它的产生并不是为了实用&#xff0c;只是到近代&#xff0c;它才成了寒冷地区保温必备之物&#xff0c;或是医疗防菌、工业防护用品。手套按照制作方法分为缝制、针织、浸胶等。如…

Vue3 Suspense

✨ 专栏介绍 在当今Web开发领域中&#xff0c;构建交互性强、可复用且易于维护的用户界面是至关重要的。而Vue.js作为一款现代化且流行的JavaScript框架&#xff0c;正是为了满足这些需求而诞生。它采用了MVVM架构模式&#xff0c;并通过数据驱动和组件化的方式&#xff0c;使…

Vite插件自动编译svg图标为字体

前言 今天来点儿6的.本文或许需要花费点时间才能理解. 目前是草稿阶段,比较凌乱,许多部分没有详细说明,日后有空更新补充. 本文主要提供解决思路,请按需调整. 很多时候我们在开发阶段是不能确定使用哪些图标的,它会随着开发不停的新增或调整. 所以我一般会从iconfont直接下载…

「Qt Widget中文示例指南」如何实现一个日历?(三)

Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写&#xff0c;所有平台无差别运行&#xff0c;更提供了几乎所有开发过程中需要用到的工具。如今&#xff0c;Qt已被运用于超过70个行业、数千家企业&#xff0c;支持数百万设备及应用。 本文中的CalendarWi…

RabbitMQ中交换机的应用 ,原理 ,案例的实现

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是平顶山大师&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《RabbitMQ中交换机的应用及原理&#xff0c;案…

如何保证缓存与数据库双写时的数据一致性?

背景&#xff1a;使用到缓存&#xff0c;无论是本地内存做缓存还是使用 Redis 做缓存&#xff0c;那么就会存在数据同步的问题&#xff0c;因为配置信息缓存在内存中&#xff0c;而内存时无法感知到数据在数据库的修改。这样就会造成数据库中的数据与缓存中数据不一致的问题。 …

代码中遇到的问题2

目录 记录: 好处&#xff1a; 问题一&#xff1a; 解答: 问题二: 解答: 常见类型问题: 记录: string connStr ConfigurationManager.ConnectionStrings["connStr"].ConnectionString; 在代码中写上这段代码&#xff0c;将连接数据库的代码语句放到&#xff…

安全基础~通用漏洞2

文章目录 知识补充盲注Boolean盲注延时盲注报错注入二次注入 知识补充 盲注常用 if(条件,5,0) #条件成立 返回5 反之 返回0 left(database(),1)&#xff0c;database() #left(a,b)从左侧截取a的前b位 盲注 盲注就是在注入过程中&#xff0c;获取的数据不能回显至前端页面。 …