【Qt开发】调试log日志QDebug重定向输出到textEdit等控件(qInstallMessageHandler回调函数)

ops/2024/9/18 12:13:20/ 标签: qt, mcu, 物联网, iot, 嵌入式, 上位机

【Qt开发】调试log日志QDebug重定向输出到textEdit等控件(qInstallMessageHandler回调函数)

文章目录

  • Log输出方式
  • qInstallMessageHandler回调函数
  • 线程安全
  • textEdit控件
  • 附录:C语言到C++的入门知识点(主要适用于C语言精通到Qt的C++开发入门)
    • C语言与C++的不同
    • C++中写C语言代码
    • C语言到C++的知识点
    • Qt开发中需要了解的C++基础知识
      • namespace
      • 输入输出
      • 字符串类型
      • class类
        • 构造函数和析构函数(解析函数)
        • 类的继承

Log输出方式

Qt有Debug、Warning、Info、Critical、Fatal五种级别的调试信息。

qDebug--------调试信息
qWarning--------警告信息
qInfo--------警告信息
qCritical--------严重错误
qFatal--------致命错误

分别由qDebug、qWarning、qCritical、qFatal等函数进行调用

调用时 与cout用法相同
如:

qDebug()<<"timerEvent 1\n";

在进行调试时 可以输出到IDE的终端下面 但是不会在窗口中显示
为了输出到窗口 则需要进行重定向

qInstallMessageHandler回调函数

Qt5提供了qInstallMessageHandler函数
用于申请一个回调

函数原型:

typedef void (*QtMessageHandler)(QtMsgType, const QMessageLogContext &, const QString &);
Q_CORE_EXPORT QtMessageHandler qInstallMessageHandler(QtMessageHandler);

申请后 每次发生QDebug等数据 都会跳到回调中

我的回调函数如下:

void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{static QMutex MessageOutput_Mutex;MessageOutput_Mutex.lock();(void)context;QByteArray localMsg = msg.toLocal8Bit();//信息分类QString strMsg("");switch(type){case QtDebugMsg:strMsg = QString("Debug:");break;case QtInfoMsg:strMsg = QString("Info:");break;case QtWarningMsg:strMsg = QString("Warning:");break;case QtCriticalMsg:strMsg = QString("Critical:");break;case QtFatalMsg:strMsg = QString("Fatal:");break;default:break;}// 设置输出信息格式QString strDateTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");QString strMessage = QString("%1 %2 %3").arg(strDateTime,strMsg,localMsg.constData());pw->debug_text->insertPlainText(strMessage);MessageOutput_Mutex.unlock();
}

注册方法:

qInstallMessageHandler(myMessageOutput);

几种传参就是类型、位置和消息内容
context位置包括被调用时的文件名、函数名称、行数等等

由于我是直接用Qt Creator直接生成的工程 MainWindow定义的w在mian函数中调用
所以需要用一个全局变量转一下

MainWindow *pw = nullptr;
int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;pw=&w;w.show();return a.exec();
}

消息处理后用

pw->debug_text->insertPlainText(strMessage);

发送到textEdit控件

最终效果
在这里插入图片描述

线程安全

如果你用到了多线程 则可能多次调用QDebug 造成多次回调
则为了安全 加了一个互斥锁

    static QMutex MessageOutput_Mutex;MessageOutput_Mutex.lock();

MessageOutput_Mutex.unlock();

textEdit控件

定义就不讲了 我是用ui直接设计的 但设计的出来都是私有成员 所以得加个公有成员指向他

QTextEdit *debug_text;
debug_text=this->ui->textEdit_2;

可以用函数设置最大行数

debug_text->document()->setMaximumBlockCount(500);

另外 在槽函数textChanged()中 加入下拉框置底的配置

void MainWindow::on_textEdit_2_textChanged()
{this->ui->textEdit_2->moveCursor(QTextCursor::End);
}

附录:C语言到C++的入门知识点(主要适用于C语言精通到Qt的C++开发入门)

C语言与C++的不同

C语言是一门主要是面向工程的语言
C++则是面向对象

C语言中 某些功能实现起来较为繁琐
比如结构体定义:

一般写作:

typedef struct stu_A
{
}A;

也可以写作:

typedef struct 
{
}A;

但 大括号后面的名称是不可省去的

不过 C++的写法就比较简单
除了支持上述写法外

也支持直接声明

typedef struct A
{
}

另外 C++是完全支持C语言库和语法的
不过C++里面的库也有些很方便的高级功能用法 只不过实现起来可能不如C的速度快

再者 C语言与C++的编译流程不一样
C语言没有函数重载 所以给编译器传参就是直接传函数名称
但是C++除了传函数名称外 还会穿函数的参数、类型等等 以实现函数重载

C++中写C语言代码

上文提到 C++可以完全兼容C的写法
但是编译流程也还是不一样
所以如果在编译层面进行C语言代码编译 则通常用以下方法:

extern "C"
{
...
}

表面大括号内的内容用C的方法进行编译

另外 如果还是用C++的编译器 但要实现C语言函数 则需要用到C语言的库

在C语言中 我们一般用如下方法导入库

#include <stdio.h>

此方法同样适用于C++ 但是C++可以更方便的写成去掉.h的方式
比如:

#include <iostream>

在C++中 为了调用C语言的库 可以采用在原库名称前加一个"c"的方式导入
如:

#include <cstdio>

这样就可以使用printf等函数了 甚至比C++的std方法更快

C语言到C++的知识点

在这里插入图片描述

Qt开发中需要了解的C++基础知识

namespace

C++面向对象的特性下诞生的一个名称
表示某个函数、变量在某个集合下 用作namespace
比如 <iostream>库中的关键字cin在std下 则写作std::cin
std就是namespace
::表示某空间下的某某
前面是空间名称 后面是变量、函数名称

using namespace可以告诉编译器以下都用xx名称空间
比如:

using namespace std;
cout<<"a";

如果没有告诉编译器所使用的空间名称 则要写成:

std::cout<<"a";

同样 可以自定义某一段代码属于哪个空间:

namespace xx
{
...
}

输入输出

在C++中 用iostream作为输入输出流的库

#include <iostream>

用cin和cout关键字进行输入和输出
如:

using namespace std;
int a=0;
cin>>a; //输入到acout<<a;  //输出a

类比scanf和printf
同样 还有一个关键字endl表示换行
cout和cin的传参是不固定的
由编译器自行裁定

字符串类型

在C语言中 常用char *表示字符串
但是在C++中 可以直接用string类型
比如:

char * s="456";
string str="123";

由于cout的特性 这两种字符串都可以直接打印
但如果使用C语言中printf的打印方式时 采用%s方式打印字符串 则不能传入string类型

class类

C++的核心就是class
同Python等支持面向对象的语言一样
可以理解成一个支持函数、继承、自动初始化、销毁的结构体
在class类中 有private私有、public公有变量
前者只能内部访问 后者可以外部调用使用
如:

class A
{
public:
int a;
private:
int b;
}

a可以用A.a的方式方位 b则外部无法访问

构造函数和析构函数(解析函数)

构造函数可以理解成对类的初始化 反之析构函数则是退出时进行销毁前的函数
两者需要与类的名称相同 析构函数则在前面加一个~表示非
如:

class A
{
public:
int a;
A();
~A();
private:
int b;
}A::A()
{
...
}A::~A()
{
...
}

构造函数可以定义传参 析构函数则不行

类的继承

如果有两个类A和B 想让A里面包含B 则可以写作继承的写法
继承后 A类的变量可以直接调用B下面的成员
如:

class B
{
int b;
}
class A: public B
{
int a;
}

在定义A后 可以访问到B的成员b 当然 继承也可以私有


http://www.ppmy.cn/ops/89629.html

相关文章

ffmpeg之内存对齐简要说明

目录 引文 行字节数的计算 ffmpeg中的align ffmpeg中的linesize 内容参考 引文 在ffmpeg的使用过程中有时会发现align这个参数&#xff0c;那么这个参数代表什么意思&#xff0c;不同的值会产生什么影响呢&#xff0c;详见下文。 行字节数的计算 理解内存对齐之前首先要…

Python爬虫技术 第33节 未来趋势和技术发展

网络爬虫&#xff08;Web crawler&#xff09;是一种自动化的程序或脚本&#xff0c;用于遍历互联网上的网页并收集所需的数据。爬虫技术在许多领域都有广泛的应用&#xff0c;从搜索引擎到数据分析、市场研究、竞争情报等。 爬虫技术的基础 基本原理&#xff1a; URL管理&…

周末总结(2024/08/04)

工作 人际关系核心实践&#xff1a; 要学会随时回应别人的善意&#xff0c;执行时间控制在5分钟以内 坚持每天早会打招呼 遇到接不住的话题时拉低自己&#xff0c;抬高别人(无阴阳气息) 朋友圈点赞控制在5min以内&#xff0c;职场社交不要放在5min以内 职场的人际关系在面对利…

Opencv学习-图像翻转变换

1. flip函数介绍&#xff08;翻转&#xff09; void cv::flip(InputArray src, OutputArray dst, int flipCode ) src&#xff1a;输入图像。 dst&#xff1a;输出图像&#xff0c;与 src 具有相同的大小、数据类型及通道数。 flipCode&#xff1a;翻转方式标志。数值大于 0 表…

Python应用—利用opencv实现图像匹配

1.创作需求 我们通常需要从一幅图中找到自己想要的信息,例如从一堆表情中找到,自己需要的表情。 2.创作思路 1.使用模板图片作为卷积核与原图进行卷积运算,得出匹配度超过某一阈值的范围。 2.对该部分进行框选 3.工具 主要使用opencv库实现,通过 cv2.matchTemplate(…

Arduino PID库 (2) –微分导致的过冲

Arduino PID库 &#xff08;2&#xff09; – Derivative Kick 参考&#xff1a;手把手教你看懂并理解Arduino PID控制库——微分冲击 pid内容索引-CSDN博客 Arduino PID库 &#xff08;1&#xff09;– 简介 问题 此修改将稍微调整derivative term。目标是消除一种称为“…

比较一下React与Vue

React和Vue都是现代前端开发中广泛使用的JavaScript库&#xff0c;它们各自具有独特的特点和优势。以下是对React和Vue的比较&#xff1a; 1. 开发模式和范式 React&#xff1a; 本质是一个前端组件框架&#xff0c;由后端组件演化而来。鼓励将UI分解为小的、独立的、可复用的…

在java java.util.Date 已知逝去时间怎么求年月日

可以通过以下步骤来求解已知逝去时间的年月日&#xff1a; 获取当前日期和逝去时间&#xff1a; Date currentDate new Date(); // 获取当前日期 Date goneDate ...; // 已知的逝去时间计算逝去时间的毫秒数差&#xff1a; long timeDiff currentDate.getTime() - goneDate.…

【C++】入门基础知识

河流之所以能够到达目的地&#xff0c;是因为它懂得怎样避开障碍。&#x1f493;&#x1f493;&#x1f493; 目录 ✨说在前面 &#x1f34b;知识点一&#xff1a;C的发展历史 • &#x1f330;1.C发展历史 • &#x1f330;2.C的迭代与更新 • &#x1f330;3.编程语言排…

H5 使用微信地址

效果图 1.先引入sdk 文件 $.ajax({type: "get",url: baseUrl "api/wechat/Pubaccount/jssdk?url" linkurl,//请求接口&#xff0c;获取授权success:function(data){let res data;jWeixin.config({debug: false,appId: res.appId,timestamp: res.time…

JVM的组成 -- 字节码文件

类加载器(ClassLoader)&#xff1a;将字节码文件加载到内存中运行时数据区(JVM管理的内存)&#xff1a;负责管理JVM使用的内存&#xff0c;比如创建对象和销毁对象执行引擎&#xff1a;即时编译器、解释器、垃圾回收器。负责本地接口的调用本地接口&#xff1a;native方法&…

Unity热更——ILRuntime安装接入

一、ILRuntime相关地址 1、官网文档地址 2、GitHub上开源的ILRuntime项目工程 3、GitHub上的官方ILRuntime-Unity实例工程 4、官方视频教程-Unity中文课堂&#xff08;需付费&#xff09; 5、ILRuntime入门笔记-赵青青-博客园 6、ILRuntime 的学习-简书 二、ILRuntime…

GitLab的安装步骤与代码拉取上传操作

一、GitLab的安装 详情见如下博客链接&#xff1a;gitlab安装 二、GitLab配置ssh key &#xff08;1&#xff09;打开Git Bash终端生成SSH和添加步骤 1、全局配置git用户名 git config --global user.name "xxx"注意&#xff1a;xxx为你自己gitlab的名字 2、全局…

一篇了解:性能测试工具——JMeter的安装

一、下载 环境要求&#xff1a;Java版本在8及以上。 安装链接&#xff1a;JMeter安装链接 下载压缩包之后解压即可。 二、配置 解压之后进入到bin目录下&#xff0c;双击jmeter.bat即可进入到该软件。 但是有一种更方便的方式进入jmeter软件&#xff1a; 复制该文件的bin文件…

智能小程序 Ray 开发面板 SDK 智能设备模型通用能力 —— 一键执行使用指南

使用 起步 SmartTapToRunAbility 自 ray-js/panel-sdk1.11.0 开始加入。 基础用法 以下为基础 JS 的接入示例&#xff1a; import { SmartTapToRunAbility } from ray-js/panel-sdk;// 创建一个 TapToRun 实例 const TapToRun new SmartTapToRunAbility().init();// 调用…

vue3+vite全局引入less变量和函数

需要在vite配置 plugins: [css: {preprocessorOptions: {less: {additionalData: import "./src/styles/variables.module.less"; import "./src/views/Visualization/component/ViewportCom/px2viewport.less";,javascriptEnabled: true}}}, ]多个文件按…

OCR图片矫正、表格检测及裁剪综合实践

问题描述 实际工程中&#xff0c;我们经常需要对图片进行预处理&#xff0c;比如&#xff1a; 1、图片是倾斜的 2、图片背景需要处理掉 3、图片的公章需要剔除 4、图片过暗&#xff0c;过亮 5、图片表格检测 6、图片表格版面分析 。。。。。。等等各种情况。 结果展示…

单细胞Seurat的umi矩阵-与feature、counts(用于质控)

目录 关于umi矩阵学习 用umi计算feature、counts值 ①meta数据查看 ②Count和Feature计算(生成Seurat时自动计算) 1)提取UMI矩阵 2)计算 其他指标 评估质量指标(重点) 1)UMI计数 2)基因计数 3)UMIs vs. genes detected 4)线粒体计数比率 5)综合过滤 过…

【SpringBoot3】场景整合(实战)

0 环境准备 0.0 云服务器 阿里云、腾讯云、华为云 服务器开通&#xff1b; 按量付费&#xff0c;省钱省心 安装以下组件&#xff1a;docker、redis、kafka、prometheus、grafana 下载windterm&#xff1a; https://github.com/kingToolbox/WindTerm/releases/download/2.5…

如何开启idea中的断言功能?

目录 一、什么是断言&#xff1f; 二、Java断言的语法 三、开启断言 一、什么是断言&#xff1f; 断言&#xff08;assert&#xff09;是 Java 中的一条语句&#xff0c;一种在程序中的逻辑&#xff08;如一个结果为真或假的逻辑判断式&#xff09;&#xff0c;目的是验证软…