qDebug用法详解

qDebug用法详解本文介绍了 Qt 调试工具 qDebug 的使用方法 包括流方式和占位方式输出 如何支持自定义结构体输出 以及如何重定向 qDebug 输出到文件

大家好,欢迎来到IT知识分享网。

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

推荐关注

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/112139.html

(0)
上一篇 2026-01-20 14:02
下一篇 2026-01-20 14:15

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信