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

这篇具有很好参考价值的文章主要介绍了Qt解析含颜色的QString字符串显示到控件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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种情况的处理规则如图:

Qt解析含颜色的QString字符串显示到控件,qt,开发语言

代码实现:

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
            {
                //取末尾标签后面的所有内容显示
                //如果更改了颜色,送到显示的字符串为空,颜色更改会无效,继续保持上一个颜色
                if(match.capturedEnd() != string_length) 
                { 
                    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");

显示结果:

Qt解析含颜色的QString字符串显示到控件,qt,开发语言

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时,一定要将指针置为空,不然程序闪退。文章来源地址https://www.toymoban.com/news/detail-824889.html

到了这里,关于Qt解析含颜色的QString字符串显示到控件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用v-html进行渲染如何使标签按照字符串显示,特殊样式标签(自己添加的部分)按照标签解析

    使用v-html进行渲染如何使标签按照字符串显示,特殊样式标签(自己添加的部分)按照标签解析 需求:是内容里如果含有含有www.baidu.com这种链接高亮显示 解决办法: 首先拿到需要回显的内容content对内容进行转义escapeHTML,之后再去判断是否是链接进行高亮添加 代码如下

    2024年02月16日
    浏览(44)
  • mysql 解析json字符串、数组字符串、json数组字符串

    笔者使用mysql 5.7进行了一次json字符串的解析,因为一直在搞大数据相关的数据库、olap等,太久没有用mysql5.x的版本,一些函数已经不知道支不支持,我的同事建议我使用like、rlike模糊匹配的方式,身为数据人我不太喜欢用这种手段,因为他们比较低效。于是我想这里总结一下

    2024年02月16日
    浏览(56)
  • 3. 51——LCD1602显示 字符、字符串、数字

    显示开关控制指令(功能:控制显示器开/关 光标显示/关闭 是否闪烁) 进入模式设置指令(功能:每写入一位数据后光标的移动 左/右 显示屏不移动/整体右移 ) 功能设定指令(功能:设定数据总线的位数 显示的行数 字型 ) 清屏指令(功能:清屏显示空白 光标归位 地址

    2023年04月08日
    浏览(36)
  • 深入解析C语言中的字符串和字符串处理函数

    标题:详解C语言中的字符串和字符串处理函数 目录: 1.引言 2.什么是C语言中的字符串 3.字符串的表示方式 4.C语言中的字符串处理函数 5.例子:使用字符串处理函数的示例代码 6.总结 在C语言中,字符串是一种常见的数据类型,用于存储一串字符。本篇博客将详细介绍C语言中

    2024年02月15日
    浏览(52)
  • 从键盘输入一个字符串,将此字符串按字符的ASCII码值从小到大排序,并显示排序后的字符串。

    题面: 字符串排序:要求编写程序,将给定字符串中的字符,按照ASCII码顺序从小到大排序后输出。 输入格式: 输入是一个以回车结束的非空字符串。 输出格式: 输出排序后的结果字符串。 输入样例: bfh3q487ybefg734 输出样例: 3344778bbeffghqy 思路: Dwl同学一开始给我的代码

    2024年02月05日
    浏览(74)
  • 字符串的全面解析

    目录 前言: 字符串的赋值   字符串的初始赋值两种:   输出的形式:   输入赋值四种方法:   在函数中的赋值(复制): 小问题: 字符串处理函数string: 多维字符串: 为什么非要在字符串后加\\\'\\0\\\'的问题。 子函数调用字符串: 字符串的错误使用方法: 通过单个元素的比较

    2024年02月07日
    浏览(38)
  • 字符函数和字符串函数解析及模拟实现

    字符串以’\\0’作为结束标志,strlen函数返回的是在字符串中’\\0’前面出现过的字符个数(不包括’\\0’)。 参数指向的字符串必须以’\\0’结束。 注意函数的返回值位size_t, 是无符号的 。 Copies the C string pointed by source into the array pointed by destination, including the terminating null c

    2024年02月16日
    浏览(47)
  • 解析GPS数据(长字符串解析示例)

    这里GPS一般返回的都是大量的数据,而且是一行行的那种,大部分数据也不太用的到,所以这个时候用串口DMA空闲中断其实就意义不大,这样我们就可以用一种新的思路来进行数据解析,专门针对这样的数据!!! 这里我用的大概长这样,还有很多其他版本的,不过区别不大

    2024年02月08日
    浏览(45)
  • QT生成固定长度的随机字符串

    最近项目中有一个需要使用QT生成固定长度随机字符串的需求,需求也很简单,就是生成一个n位的仅包含0-9以及大写字母的字符串,因为这也是第一次使用QT自身的随机数,这里就做一下简单记录。 废话不多说,直接上代码。 View Code  这段代码逻辑也很简单,以当前的时间戳

    2024年03月13日
    浏览(61)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包