高亮下位机温湿度

效果如下:

如何对QTextEditor中的内容进行高亮和格式化显示:

  1. 首先我们要自定义一个类WenshiduHighlighter,继承自QSyntaxHighlighter
  2. 实现构造函数,在构造函数中将需要匹配的正则和对应的格式创建,存到成员变量中
  3. 重写父类的void highlightBlock(const QString &text) = 0函数,在该函数中对text利用之前创建的正则进行匹配,若匹配上了,则调用父类的setFormat方法将对应的格式设置进去

代码如下:

cpp 复制代码
//自定义一个高亮类,需要继承自抽象类QSyntaxHighlighter
class WenshiduHighlighter:public QSyntaxHighlighter
{
    Q_OBJECT
public:

    //定义高亮规则结构体
    struct HighlightRule
    {
        //需要匹配的正则(通过正则来找到你要想高亮的那一部分字符)
        QRegularExpression pattern;

        //正则匹配到的字符串对应的格式
        QTextCharFormat format;
    };

    //实现构造函数,参数就是QTextEditor里面的内容,QTextDocument;
    //该参数主要是为了用来初始化父类QSyntaxHighlighter
    WenshiduHighlighter(QTextDocument* doc):QSyntaxHighlighter(doc)
    {
        //在构造函数中,初始化highlight_rules,创建想要高亮的内容和对应的格式
        HighlightRule rule;

        //下面就属于正则表达式的内容了 ,正则怎么写不赘述

        //日期,在一对[]内
        rule.pattern=QRegularExpression(R"(\[.*\])");
        QTextCharFormat datetime_format;
        datetime_format.setForeground(QColor(85,85,85));//设置前景色
        datetime_format.setBackground(QColor(240,240,240));//设置背景色
        datetime_format.setFontWeight(QFont::Bold);//设置加粗
        datetime_format.setFontFamily("Consolas");
        rule.format=datetime_format;
        highlight_rules.push_back(rule);

        //温度key
        rule.pattern=QRegularExpression(R"(Temperature)");
        QTextCharFormat temper_key_format;
        temper_key_format.setForeground(QColor(180,30,110));
        temper_key_format.setFontFamily("Consolas");
        rule.format=temper_key_format;
        highlight_rules.push_back(rule);

        //温度value
        rule.pattern=QRegularExpression(R"((?<=Temperature:)\s*-*\d+℃)");//反向预查,以Temperature:开始
        QTextCharFormat temper_val_format;
        temper_val_format.setForeground(QColor(180,30,110));
        temper_val_format.setFontWeight(QFont::Bold);
        temper_val_format.setFontFamily("Consolas");
        rule.format=temper_val_format;
        highlight_rules.push_back(rule);


        //湿度key
        rule.pattern=QRegularExpression(R"(Humidity)");
        QTextCharFormat humi_key_format;
        humi_key_format.setForeground(QColor(97,54,134));
        humi_key_format.setFontFamily("Consolas");
        rule.format=humi_key_format;
        highlight_rules.push_back(rule);

        //湿度value
        rule.pattern=QRegularExpression(R"((?<=Humidity:)\s*\d+%)");//反向预查
        QTextCharFormat humi_val_format;
        humi_val_format.setForeground(QColor(97,54,134));
        humi_val_format.setFontWeight(QFont::Bold);
        humi_val_format.setFontFamily("Consolas");
        rule.format=humi_val_format;
        highlight_rules.push_back(rule);

        //正常
        rule.pattern=QRegularExpression(R"(\(Normal\))");
        QTextCharFormat normal_format;
        normal_format.setForeground(Qt::darkGreen);
        normal_format.setFontFamily("Consolas");
        rule.format=normal_format;
        highlight_rules.push_back(rule);

        //偏低
        rule.pattern=QRegularExpression(R"(\(↓Lower\))");
        QTextCharFormat lower_format;
        lower_format.setForeground(Qt::white);
        lower_format.setBackground(Qt::darkBlue);
        lower_format.setFontWeight(QFont::Bold);
        lower_format.setFontFamily("Consolas");
        rule.format=lower_format;
        highlight_rules.push_back(rule);


        //偏高
        rule.pattern=QRegularExpression(R"(\(↑Upper\))");
        QTextCharFormat upper_format;
        upper_format.setForeground(Qt::white);
        upper_format.setBackground(QColor(220,50,50));
        upper_format.setFontWeight(QFont::Bold);
        upper_format.setFontFamily("Consolas");
        rule.format=upper_format;
        highlight_rules.push_back(rule);
    }

    ~WenshiduHighlighter()=default;

protected:
    //最后,我们要重写父类的抽象接口void highlightBlock(const QString &text) = 0
    //这个函数的参数text,就是构造传进来的doc的每一行,
    //该父类会自动把doc的每一行都来调用这个函数来进行匹配+高亮
    void highlightBlock(const QString &text) override
    {
        //遍历所有的规则,来给每一行的数据匹配后设置格式
        for(const auto& itor:highlight_rules)
        {
            auto match_list=itor.pattern.globalMatch(text);
            //如果匹配到了
            while(match_list.hasNext())
            {
                auto match_result=match_list.next();

                //最后调用父类的setFormat方法设置格式
                //参数1:匹配到字符的开始索引
                //参数2:匹配到字符的长度
                //参数3:预先构造好的格式
                setFormat(match_result.capturedStart(),
                          match_result.capturedLength(),
                          itor.format);
            }
        }
    }

private:
    std::vector<HighlightRule> highlight_rules;

};

如何使用

  • 设置高亮,直接new一个WenshiduHighlighter,然后将QTextEditor内部文档的指针传过来
  • 取消高亮,直接delete掉前面new出来的WenshiduHighlighter

代码如下:

cpp 复制代码
class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr):QWidget(parent)
    {
        setStyleSheet(R"(QPushButton{
           font-family:"Microsoft YaHei";
           font-size:13px;
           font-weight:bold;
         }
         QCheckBox{
           font-family:"Microsoft YaHei";
           font-size:13px;
           font-weight:bold;
         })");
        //整个窗口垂直布局
        QVBoxLayout* v_box=new QVBoxLayout(this);

        //创建复选框和两个按钮,三者采用水平布局
        QHBoxLayout* h_box=new QHBoxLayout();

        format_box=new QCheckBox(this);
        format_box->setText("下位机温湿度高亮");
        h_box->addWidget(format_box);

        QSpacerItem* spacer1=new QSpacerItem(20,5,QSizePolicy::MinimumExpanding,QSizePolicy::Fixed);
        h_box->addSpacerItem(spacer1);

        btn_start_receive=new QPushButton(this);
        btn_start_receive->setText("开始接收");
        btn_start_receive->setFixedSize(80,30);
        btn_start_receive->setCursor(Qt::PointingHandCursor);
        h_box->addWidget(btn_start_receive);

        QSpacerItem* spacer2=new QSpacerItem(20,5,QSizePolicy::Fixed,QSizePolicy::Fixed);
        h_box->addSpacerItem(spacer2);

        btn_clear=new QPushButton(this);
        btn_clear->setText("清除数据");
        btn_clear->setFixedSize(80,30);
        btn_clear->setCursor(Qt::PointingHandCursor);
        h_box->addWidget(btn_clear);

        v_box->addLayout(h_box);

        //创建内容区
        edit_content=new QTextEdit(this);
        //设置为等宽字体,来使上下两行的数据对齐
        edit_content->setStyleSheet("font:16px Courier");
        v_box->addWidget(edit_content);

        resize(800,600);

        timer=new QTimer(this);

        //开始接收按钮
        //则开始一个定时器,以500ms为间隔模拟生成一条温湿度数据,追加到editor中
        connect(btn_start_receive,&QPushButton::clicked,this,[=](){
            //定时器开着,则关闭定时器,停止追加数据
            if(timer->isActive())
            {
                timer->stop();
                btn_start_receive->setText("开始接收");
            }
            else
            {
                //定时器关着,则开启定时器
                timer->start(500);
                btn_start_receive->setText("停止接收");
            }
        });

        //清除按钮
        connect(btn_clear,&QPushButton::clicked,this,[=](){
            //清除数据
            edit_content->clear();
        });

        //高亮下位机温湿度
        connect(format_box,&QCheckBox::clicked,this,[=](){
            if(format_box->isChecked())
            {
                //如何产生高亮,直接new一个温湿度高亮者,就可以高亮了
                wenshidu_highlighter=new WenshiduHighlighter(edit_content->document());
            }
            else
            {
                //如何取消高亮。直接delete将他析构好了
                delete wenshidu_highlighter;
            }
        });

        //定时器
        connect(timer,&QTimer::timeout,this,&Widget::addData);

    }
    ~Widget()=default;
protected:
    void addData()
    {
        QString str_data;
        str_data+="[";
        //日期时间
        str_data+=QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
        str_data+="]  ";

        //随机生成温度,范围【-10,50】
        int temper=-10+QRandomGenerator::global()->generate()%61;
        if(temper<10)
        {
            //arg(temper,3)表示温度占3位
            str_data+=QString("%1%2%3").arg("Temperature: ").arg(temper,3).arg("℃ (↓Lower)  ");
        }
        else if(temper>=10&& temper<30)
        {
            str_data+=QString("%1%2%3").arg("Temperature: ").arg(temper,3).arg("℃ (Normal)  ");
        }
        else
        {
            str_data+=QString("%1%2%3").arg("Temperature: ").arg(temper,3).arg("℃ (↑Upper)  ");
        }

        //随机生成湿度,范围【20,100】
        int humi=20+QRandomGenerator::global()->generate()%81;
        if(humi<40)
        {
            str_data+=QString("%1%2%3").arg("Humidity: ").arg(humi,3).arg("% (↓Lower)");
        }
        else if(humi>=40 && humi<70)
        {
            str_data+=QString("%1%2%3").arg("Humidity: ").arg(humi,3).arg("% (Normal)");
        }
        else
        {
            str_data+=QString("%1%2%3").arg("Humidity: ").arg(humi,3).arg("% (↑Upper)");
        }

        edit_content->append(str_data);

    }

private:
    QTimer* timer;

    QCheckBox* format_box;//高亮内容

    QPushButton* btn_start_receive;//接收数据

    QPushButton* btn_clear;//清除内容

    QTextEdit* edit_content;//内容区

    WenshiduHighlighter* wenshidu_highlighter;

};

学习链接:https://github.com/0voice

相关推荐
獨枭3 小时前
CMake 构建项目并整理头文件和库文件
c++·github·cmake
码农W4 小时前
QT--静态插件、动态插件
开发语言·qt
小王爱吃月亮糖5 小时前
C++的23种设计模式
开发语言·c++·qt·算法·设计模式·ecmascript
小哈龙7 小时前
c++ 类似与c# 线程 AutoResetEvent 和 ManualResetEvent的实现
c++·c#·多线程
yuanbenshidiaos7 小时前
C++--------------树
java·数据库·c++
海螺姑娘的小魏7 小时前
Effective C++ 条款 15:在资源管理类中提供对原始资源的访问
开发语言·c++
青青丘比特9 小时前
STL.string(下)
开发语言·c++
jjjxxxhhh12310 小时前
C++ 模板是为了解决啥问题
开发语言·c++·算法
c++初学者ABC10 小时前
GESP2级2403 小杨的日字矩阵
c++·算法
代码小将10 小时前
PTA数据结构编程题7-1最大子列和问题
数据结构·c++·笔记·学习·算法