Qt有Debug、Warning、Info、Critical、Fatal五种级别的调试信息。
qDebug:调试信息
qWarning:警告信息
qInfo:警告信息
qCritical:严重错误
qFatal:致命错误
Qt4提供了qInstallMsgHandler(Qt5:qInstallMessageHandler)对qDebug、qWarning、qCritical、qFatal等函数输出信息的重定向处理。
qInstallMsgHandler是一个回调函数,由qDebug、qWarnng、qCritical、qFatal函数进行触发,qDebug、qWarnng、qCritical、qFatal函数处理的消息文本会被qInstallMsgHandler所指向的回调函数截获,允许用户自己来处理输出的消息文本。
一、来看官方的例子:
void outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg) { QString text; switch(type) { case QtDebugMsg: text = QString("Debug:"); break; case QtWarningMsg: text = QString("Warning:"); break; case QtCriticalMsg: text = QString("Critical:"); break; case QtFatalMsg: text = QString("Fatal:"); } QDateTime current_date_time = QDateTime::currentDateTime(); QString current_date = current_date_time.toString("yyyy-MM-dd hh:mm:ss ddd"); QString message = text.append(msg).append("(").append(current_date).append(")"); QFile file("log.txt"); file.open(QIODevice::WriteOnly | QIODevice::Append); QTextStream text_stream(&file); text_stream<<message<<"\r\n"; file.close(); } int main(int argc, char *argv[]) { QApplication app(argc, argv); //注册MessageHandler qInstallMessageHandler(outputMessage); //打印日志到文件中 qDebug("This is a debug message"); qWarning("This is a warning message"); qCritical("This is a critical message"); qFatal("This is a fatal message"); return app.exec(); }
Qt自带5个向外写警告和调试文本的方法。可以把它们使用在如下目的:
qDebug():用于写自定调试信息的输出;
qWarning():用于报告程序中的警告和可恢复的错误;
qCritical():用于写关键错误信息和报告系统错误;
qFatal():用于退出前简要地描述致命错误消息;
qInfo():用于写自定调试信息的输出。
如果包含<QtDebug>头文件,qDebug()可以当做输出流来使用。例如:
qDebug() << "Widget" << widget << "at position" << widget->pos();
二、开源项目
http://www.qtcn.org/bbs/read-htm-tid-85387-page-e.html使用了qInstallMessageHandler的机制,封装了日志库。
本人在它基础之上,略微修改,封装了更强大和易用的日志库。
void Log(QtMsgType type, const QMessageLogContext &context, const QString &msg) #endif { //加锁,防止多线程中qdebug太频繁导致崩溃 QMutex mutex; QMutexLocker locker(&mutex); //这里可以根据不同的类型加上不同的头部用于区分 //Release 版本默认不包含这些信息:文件名、函数名、行数,需要在.pro项目文件加入以下代码,加入后最好重新构建项目使之生效: //DEFINES += QT_MESSAGELOGCONTEXT //此外,在.pro文件定义以下的宏,可以屏蔽相应的日志输出 //DEFINES += QT_NO_WARNING_OUTPUT //DEFINES += QT_NO_DEBUG_OUTPUT //DEFINES += QT_NO_INFO_OUTPUT QByteArray localMsg = msg.toLocal8Bit(); QString content; switch (type) { case QtDebugMsg: content = QString("Debug: %1 (%2:%3, %4)\n").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function); break; case QtInfoMsg: content = QString("Info: %1 (%2:%3, %4)\n").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function); break; case QtWarningMsg: content = QString("Warning: %1 (%2:%3, %4)\n").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function); break; case QtCriticalMsg: content = QString("Critical: %1 (%2:%3, %4)\n").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function); break; case QtFatalMsg: content = QString("Fatal: %1 (%2:%3, %4)\n").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function); break; default: content = QString("Default: %1 (%2:%3, %4)\n").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function); break; } content = QDateTime::currentDateTime().toString("yyyy-MM-dd hh.mm.ss.zzz ") + content; SaveLog::Instance()->save(content); }
完整的工程源码请下载:https://download.csdn.net/download/libaineu2004/11058474
三、注意事项:
1、Release 版本默认不包含这些信息:文件名、函数名、行数,需要在.pro项目文件加入以下代码,加入后最好重新构建项目使之生效:
DEFINES += QT_MESSAGELOGCONTEXT
2、此外,在.pro文件定义以下的宏,可以屏蔽相应的日志输出
DEFINES += QT_NO_WARNING_OUTPUT
DEFINES += QT_NO_DEBUG_OUTPUT
DEFINES += QT_NO_INFO_OUTPUT
记得把工程清除之后,再重新构建。
也可以灵活一点:
在.pro文件中加入
release:DEFINES += QT_NO_WARNING_OUTPUT \
QT_NO_DEBUG_OUTPUT
这样一来,编译debug不受影响,继续有输出,release的时候停止输出。
3、如果使用的IDE是Visual Studio,那么
在VC项目配置里C/C++ /Preprocessor /Preprocessor Definitions属性里面加入宏定义:
QT_MESSAGELOGCONTEXT
QT_NO_DEBUG_OUTPUT
QT_NO_WARNING_OUTPUT
四、另一个开源项目
https://github.com/francescmm/QLogger