Qt qInstallMessageHandler(自定义消息处理)

前言

Installs a Qt message handler which has been defined previously. Returns a pointer to the previous message handler.
The message handler is a function that prints out debug messages, warnings, critical and fatal error messages. The Qt library (debug mode) contains hundreds of warning messages that are printed when internal errors (usually invalid function arguments) occur. Qt built in release mode also contains such warnings unless QT_NO_WARNING_OUTPUT and/or QT_NO_DEBUG_OUTPUT have been set during compilation. If you implement your own message handler, you get total control of these messages.
The default message handler prints the message to the standard output under X11 or to the debugger under Windows. If it is a fatal message, the application aborts immediately.
Only one message handler can be defined, since this is usually done on an application-wide basis to control debug output.
To restore the message handler, call qInstallMessageHandler(0).

这是官方说明,主要的意思就是:
安装自定义的消息处理程序,返回指向上一个消息处理程序的指针。
消息处理程序是一个支持打印调试信息、警告、关键和致命错误信息的函数。Qt库(debug模式)包含数以百计的警告信息,当内部错误(通常是无效的函数参数)发生时,会打印出来。在Release模式下构建也包含这些警告,除非在编译时设置QT_NO_WARNING_OUTPUT和/或QT_NO_DEBUG_OUTPUT。如果你实现了自己的消息处理程序,你就可以完全控制这些消息。
默认消息处理程序将消息打印到 X11 下的标准输出或 Windows 下的调试器。如果是致命消息,应用程序会立即中止。
只能定义一个消息处理程序,因为这通常是在应用程序范围内完成的,以控制调试输出。
调用qInstallMessageHandler(0)可以恢复消息处理程序。

调试宏

Qt调试信息相关的宏有以下5种:

  • qDebug() :调试消息
  • qInfo():信息消息
  • qWarning():警告消息
  • qCritical() :错误消息
  • qFatal():致命错误消息

使用

在使用默认消息处理程序时,我们看一下调试输出的内容:

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 打印信息
    qDebug() << "This is a debug message";
    qDebug("This is a debug message");
    qInfo("This is a info message");
    qWarning("This is a warning message");
    qCritical("This is a critical message");
    qFatal("This is a fatal message");
    
    return a.exec();
}

输出:

This is a debug message
This is a debug message
This is a info message
This is a warning message
This is a critical message
This is a fatal message

自定义消息处理程序

我们直接拿官网的示例来测试:

#include <qapplication.h>
#include <stdio.h>
#include <stdlib.h>

void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    QByteArray localMsg = msg.toLocal8Bit();
    const char *file = context.file ? context.file : "";
    const char *function = context.function ? context.function : "";
    switch (type) {
    case QtDebugMsg:
        fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
        break;
    case QtInfoMsg:
        fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
        break;
    case QtWarningMsg:
        fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
        break;
    case QtCriticalMsg:
        fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
        break;
    case QtFatalMsg:
        fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
        break;
    }
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    // 安装消息处理程序
    auto front = qInstallMessageHandler(myMessageOutput);
    // 打印信息
    qDebug() << "This is a debug message";
    qDebug("This is a debug message");
    qInfo("This is a info message");
    qWarning("This is a warning message");
    qCritical("This is a critical message");
    qFatal("This is a fatal message");
    
    return a.exec();
}

输出:

Debug: This is a debug message (…\main.cpp:88, int __cdecl main(int,char *[]))
Debug: This is a debug message (…\main.cpp:89, int __cdecl main(int,char *[]))
Info: This is a info message (…\main.cpp:90, int __cdecl main(int,char *[]))
Warning: This is a warning message (…\main.cpp:91, int __cdecl main(int,char *[]))
Critical: This is a critical message (…\main.cpp:92, int __cdecl main(int,char *[]))
Fatal: This is a fatal message (…\main.cpp:93, int __cdecl main(int,char *[]))

从上面示例看出我们可以去规范输出的格式,那么我们能不能决定输出的地方呢?比如直接输出到文件中?

自定义输出到文件

直接上代码:

void myMessageOutputToFile(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
    QByteArray msgAry = msg.toLocal8Bit();

    QString msgTypeStr;
    switch (type) {
    case QtDebugMsg:
        msgTypeStr = QString("Debug");
        break;
    case QtInfoMsg:
        msgTypeStr = QString("Info");
        break;
    case QtWarningMsg:
        msgTypeStr = QString("Warning");
        break;
    case QtCriticalMsg:
        msgTypeStr = QString("Critical");
        break;
    case QtFatalMsg:
        msgTypeStr = QString("Fatal");
        break;
    }
    
    // 输出字符串格式化
    QString dateTimeStr = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
    QString msgStr = QString("[%1][%2] [%3:%4:%5]:%6").arg(dateTimeStr).arg(msgTypeStr)
                             .arg(context.file).arg(context.line).arg(context.function).arg(msgAry.constData());
    
    // 读写文件
    QFile file("log.txt");
    file.open(QIODevice::ReadWrite | QIODevice::Append);
    QTextStream stream(&file);
    stream << msgStr << "\r\n";
    file.flush();
    file.close();
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    // 安装消息处理程序
    auto front = qInstallMessageHandler(myMessageOutputToFile);
    
    // 打印信息
    qDebug() << "This is a debug message";
    qDebug("This is a debug message");
    qInfo("This is a info message");
    qWarning("This is a warning message");
    qCritical("This is a critical message");
    qFatal("This is a fatal message");
    
    return a.exec();
}

输出:

注意:
上面输出到文件的方法是有问题的,这里只是进行简单的测试,问题主要有:

  1. 文件每次调用都要openclose
  2. 线程不安全
  3. 没有日志缓冲,直接写文件,性能会有问题

感兴趣的可以在这个基础上,实现一个线程安全的缓冲日志库… …

相关推荐

  1. Vue:定义消息通知组件

    2024-06-15 21:44:03       47 阅读
  2. MFC 定义分发消息方法

    2024-06-15 21:44:03       42 阅读
  3. C#WPF定义消息对话框

    2024-06-15 21:44:03       87 阅读
  4. MFC模拟消息发送,定义以及系统消息

    2024-06-15 21:44:03       55 阅读
  5. Springboot定义全局异常处理

    2024-06-15 21:44:03       62 阅读
  6. nginx日志定义和统计处理

    2024-06-15 21:44:03       38 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-15 21:44:03       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-15 21:44:03       106 阅读
  3. 在Django里面运行非项目文件

    2024-06-15 21:44:03       87 阅读
  4. Python语言-面向对象

    2024-06-15 21:44:03       96 阅读

热门阅读

  1. 正则表达式

    2024-06-15 21:44:03       27 阅读
  2. MyBatis-Plus 源码解说

    2024-06-15 21:44:03       20 阅读
  3. Linux Ubuntu 24.04 C语言gcc编译过程详解

    2024-06-15 21:44:03       32 阅读
  4. mac 本地启动rocketmq

    2024-06-15 21:44:03       29 阅读
  5. SpringBoot面试准备 第一天

    2024-06-15 21:44:03       30 阅读
  6. vscode创建一个jest测试框架的项目

    2024-06-15 21:44:03       24 阅读
  7. css3新增伪元素有哪些?

    2024-06-15 21:44:03       31 阅读
  8. Android中的KeyEvent详解

    2024-06-15 21:44:03       34 阅读