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