qDebug用法详解

文章目录

  • 1.使用方法
        • 流方式输出
        • 占位方式输出
  • 2.让qDebug支持输出自定义的结构体
  • 3.重定向qDebug的输出
  • 4.指定qDebug的输出格式
        • 输出支持的格式
  • 5.pro文件中相关配置

1.使用方法


流方式输出

不用像std::out,需要在最后添加endl,使用更方便,支持常见类型直接输出,还支持Qt内置的数据类型输出,如QMap,QList,QVaraint等等,qt调试利器

QString strText = "hello";
bool bOk = true;
qDebug()<< strText << bOk;

占位方式输出

使用方式完全和printf一样,因为内部实现就是printf

qDebug("%s","hello");

Qt5源码

#define Q_ATTRIBUTE_FORMAT_PRINTF(A, B) \
         __attribute__((format(printf, (A), (B))))
         
void debug(const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(2, 3);

2.让qDebug支持输出自定义的结构体


在项目中自定义结构体非常常见,但是打印自定义结构体很麻烦,每次使用都需要逐个成员依次打印,输出起来就很麻烦。

普通实现

struct StInfo{
    int id;
    QString dev_id;
};

普通用法

StInfo stInfo;
qDebug()<< stInfo.id << stInfo.dev_id;

也有个简单的做法就是实现一个toString()方法,需要输出结构体就调用一下toString()。

升级实现

struct StInfo{
    int id;
    QString dev_id;
    QString toString()
    {
        return QString("StInfo(%1 %2)").arg(id).arg(dev_id);    
    }
};

升级用法

StInfo stInfo;
qDebug()<< stInfo.toString();

不过我们可以通过友元函数的方式重载qDebug,来支持自定义类型输出。并且还可以在结构体前后或中间随意的添加标记,诸如结构体前缀,成员变量标记,更明显的看出来这是哪个结构体的信息。

终极实现

struct StInfo{
    int id;
    QString dev_id;

    friend inline QDebug operator<<(QDebug out, const StInfo& info)
    {
        out <<" StInfo("<<info.id<<info.dev_id<<") ";
        return out;
    }
};

终极用法

StInfo info;
qDebug()<< info;

3.重定向qDebug的输出


qDebug用的正舒服,此时需要输出debug信息到文件,可通过如下方式
//声明一个全局的回调函数
void outputMsg(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    ...
    //打开文件,组织字符串写入
    ...
}

int main()
{
    ...
    //安装回调函数
    qInstallMessageHandler(outputMsg);
    ...
}

为了调试方便,我们还可以将日志通过信号输出到窗口、文件、socket、控制台中等等。实现方式均可自定义。

注意

1.该回调函数内的实现不可使用qDebug,否则会造成死递归,如需打印调试使用printf和std::out均可。

2.注意加锁以支持多线程qDebug();

调用qInstallMessageHandler,传入回调函数指针,qDebug最后的输出将会送入这个回调函数,QMessageLogContext中包含了文件名,函数名,行号等信息。msg则是输出的信息。次数实现写入文件即可。

Qt5源码中的声明

class QMessageLogContext
{
    ...
    int version;
    int line;
    const char *file;
    const char *function;
    const char *category;
    ...
};

4.指定qDebug的输出格式

一个简单的使用示例

int main()
{
    //设置qDebug的输出格式
    qSetMessagePattern("[%{type}] %{time yyyy-MM-dd hh:mm:ss.zzz}  %{function}:%{line} %{message}");

    qDebug()<<"hello";
}

控制台输出

[warning] 2021-08-19 10:10:59.886  main:32 hello

输出支持的格式

支持字段描述
%{appname}QCoreApplication::applicationName()
%{category}日志类别
%{file}源文件路径
%{function}函数名
%{line}在源文件中的行号
%{message}实际的信息
%{pid}QCoreApplication::applicationPid()
%{threadid}线程Id
%{qthreadptr}当前线程指针
%{type}“debug”, “warning”, “critical” or “fatal”
%{time process}该进程启动以来的时间
%{time boot}自软件运行以来的时间
%{time [format]}当前时间,支持自定义时间戳格式
%{backtrace [depth=N] [separator="…"]}程序异常时的堆栈信息

默认的输出格式为
“%{if-category}%{category}: %{endif}%{message}”

设置输出格式的方式支持两种,分别是环境变量和函数调用,同时使用时环境变量优先。
指定格式的时候还可以使用类型条件判断,判断条件包含在%{}中%{endif}表示该判断的逻辑结束,可以通过此功能指定不同类型消息的输出标记,以及在控制台,控制不同类型输出不同颜色。

 QT_MESSAGE_PATTERN="[%{time yyyyMMdd h:mm:ss.zzz t}
 %{if-debug}D%{endif}%{if-info}I%{endif}%{if-warning}W
 %{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{file}:%{line} - %{message}"

控制台颜色输出代码示例

不同类型的日志前缀不同的颜色码,并且该条日志输出之后,需要恢复颜色到原始状态(\033[0m),否则后续第三方库调用printf的输出会一直保持这个颜色,造成颜色显示错乱。

//CLogEvent 为作者自定义的结构体 包含日志类型(debug info...)和函数名、行号等等信息,重点关注不同类型颜色的输出实现
void CConsoleAppender::append(CLogEvent &event)
{
    if(event.level < m_enmLevel)
        return ;

    static QString arrColor[] = {"","\033[32m","\033[33m","\033[31m","\033[35m"};// 默认 绿 黄 红 紫

    fprintf(stdout,"%s %s\n\033[0m",arrColor[event.level].toStdString().c_str(),m_fmtter.fmt(event).toLocal8Bit().constData());
    fflush(stdout);
}

5.pro文件中相关配置

#release模式默认不会显示函数名,行号等信息,添加以下即可显示
DEFINES += QT_MESSAGELOGCONTEXT

#可通过环境变量配置日志格式
QT_MESSAGE_PATTERN="[%{time yyyyMMdd h:mm:ss.zzz t}
  %{if-debug}D%{endif}%{if-info}I%{endif}%{if-warning}W
  %{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{file}:%{line} - %{message}"

热门文章

暂无图片
编程学习 ·

exe4j详细使用教程(附下载安装链接)

一、exe4j介绍 ​ exe4j是一个帮助你集成Java应用程序到Windows操作环境的java可执行文件生成工具&#xff0c;无论这些应用是用于服务器&#xff0c;还是图形用户界面&#xff08;GUI&#xff09;或命令行的应用程序。如果你想在任务管理器中及Windows XP分组的用户友好任务栏…
暂无图片
编程学习 ·

AUTOSAR从入门到精通100讲(126)-浅谈车载充电系统通信方案

01 引言 本文深入研究车载充电系统策略,设计出一套基于电动汽车电池管理系统与车载充电机的CAN通信协议,可供电动汽车设计人员参考借鉴。 02 电动汽车充电系统通讯网络 电动汽车整车控制系统中采用的是CAN总线通信方式,由一个整车内部高速CAN网络、内部低速CAN网络和一个充电…
暂无图片
编程学习 ·

CMake(九):生成器表达式

当运行CMake时&#xff0c;开发人员倾向于认为它是一个简单的步骤&#xff0c;需要读取项目的CMakeLists.txt文件&#xff0c;并生成相关的特定于生成器的项目文件集(例如Visual Studio解决方案和项目文件&#xff0c;Xcode项目&#xff0c;Unix Makefiles或Ninja输入文件)。然…
暂无图片
编程学习 ·

47.第十章 网络协议和管理配置 -- 网络配置(八)

4.3.3 route 命令 路由表管理命令 路由表主要构成: Destination: 目标网络ID,表示可以到达的目标网络ID,0.0.0.0/0 表示所有未知网络,又称为默认路由,优先级最低Genmask:目标网络对应的netmaskIface: 到达对应网络,应该从当前主机哪个网卡发送出来Gateway: 到达非直连的网络,…
暂无图片
编程学习 ·

元宇宙技术基础

请看图&#xff1a; 1、通过AR、VR等交互技术提升游戏的沉浸感 回顾游戏的发展历程&#xff0c;沉浸感的提升一直是技术突破的主要方向。从《愤怒的小鸟》到CSGO,游戏建模方式从2D到3D的提升使游戏中的物体呈现立体感。玩家在游戏中可以只有切换视角&#xff0c;进而提升沉浸…
暂无图片
编程学习 ·

flink的伪分布式搭建

一 flink的伪分布式搭建 1.1 执行架构图 1.Flink程序需要提交给 Job Client2.Job Client将作业提交给 Job Manager3.Job Manager负责协调资源分配和作业执行。 资源分配完成后&#xff0c;任务将提交给相应的 Task Manage。4.Task Manager启动一个线程以开始执行。Task Manage…
暂无图片
编程学习 ·

十进制正整数与二进制字符串的转换(C++)

Function one&#xff1a; //十进制数字转成二进制字符串 string Binary(int x) {string s "";while(x){if(x % 2 0) s 0 s;else s 1 s;x / 2;}return s; } Function two&#xff1a; //二进制字符串变为十进制数字 int Decimal(string s) {int num 0, …
暂无图片
编程学习 ·

[含lw+源码等]微信小程序校园辩论管理平台+后台管理系统[包运行成功]Java毕业设计计算机毕设

项目功能简介: 《微信小程序校园辩论管理平台后台管理系统》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 本系统包含微信小程序做的辩论管理前台和Java做的后台管理系统&#xff1a; 微信小程序——辩论管理前台涉及技术&#xff1a;WXML 和 WXS…
暂无图片
编程学习 ·

树莓派驱动DHT11温湿度传感器

1&#xff0c;直接使用python库 代码如下 import RPi.GPIO as GPIO import dht11 import time import datetimeGPIO.setwarnings(True) GPIO.setmode(GPIO.BCM)instance dht11.DHT11(pin14)try:while True:result instance.read()if result.is_valid():print(ok)print(&quo…
暂无图片
编程学习 ·

ELK简介

ELK简介 ELK是三个开源软件的缩写&#xff0c;Elasticsearch、Logstash、Kibana。它们都是开源软件。不过现在还新增了一个 Beats&#xff0c;它是一个轻量级的日志收集处理工具(Agent)&#xff0c;Beats 占用资源少&#xff0c;适合于在各个服务器上搜集日志后传输给 Logstas…
暂无图片
编程学习 ·

Linux 基础

通常大数据框架都部署在 Linux 服务器上&#xff0c;所以需要具备一定的 Linux 知识。Linux 书籍当中比较著名的是 《鸟哥私房菜》系列&#xff0c;这个系列很全面也很经典。但如果你希望能够快速地入门&#xff0c;这里推荐《Linux 就该这么学》&#xff0c;其网站上有免费的电…
暂无图片
编程学习 ·

Windows2022 无线网卡装不上驱动

想来 Windows2022 和 windows10/11 的驱动应该差不多通用的&#xff0c;但是死活装不上呢&#xff1f; 搜一下&#xff0c;有人提到 “默认安装时‘无线LAN服务’是关闭的&#xff0c;如果需要开启&#xff0c;只需要在“添加角色和功能”中&#xff0c;选择开启“无线LAN服务…
暂无图片
编程学习 ·

【嵌入式面试宝典】版本控制工具Git常用命令总结

目录 创建仓库 查看信息 版本回退 版本检出 远程库 Git 创建仓库 git initgit add <file> 可反复多次使用&#xff0c;添加多个文件git commit -m <message> 查看信息 git status 仓库当前的状态git diff 差异对比git log 历史记录&#xff0c;提交日志--pret…
暂无图片
编程学习 ·

用Postman生成测试报告

newman newman是一款基于nodejs开发的可以运行postman脚本的工具&#xff0c;使用Newman&#xff0c;可以直接从命令运行和测试postman集合。 安装nodejs 下载地址&#xff1a;https://nodejs.org/en/download/ 选择自己系统相对应的版本内容进行下载&#xff0c;然后傻瓜式安…
暂无图片
编程学习 ·

Java面向对象之多态、向上转型和向下转型

文章目录前言一、多态二、引用类型之间的转换Ⅰ.向上转型Ⅱ.向下转型总结前言 今天继续Java面向对象的学习&#xff0c;学习面向对象的第三大特征&#xff1a;多态&#xff0c;了解多态的意义&#xff0c;以及两种引用类型之间的转换&#xff1a;向上转型、向下转型。  希望能…