qDebug用法详解

本文介绍了Qt调试工具qDebug的使用方法,包括流方式和占位方式输出,如何支持自定义结构体输出,以及如何重定向qDebug输出到文件。此外,还展示了如何指定qDebug的输出格式,并提供了在pro文件中的相关配置。通过这些技巧,可以更高效地进行Qt应用的调试工作。
摘要由CSDN通过智能技术生成

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}"

推荐关注

欢迎关注《每周Qt》,学习最新的Qt知识。
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是唐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值