Qt之QDebug日志输出(含源码)

文章目录

一、日志输出示例

1.Qt帮助示例源码

Qt帮助示例源码,自定义输出格式(通过传入的QMessageLogContext对象获取相关信息),但并未输出文件。

2.纯净日志输出(日志内容所见即所得)

输出函数传入的什么值则把什么值写入到日志文件中。

3.Qt格式化输出Qt输出栏(输出至Qt输出栏,不包括文件)

使用qSetMessagePattern格式化输出内容,并将输出值写入至日志文件中。

4.Qt格式化输出到文件

使用qSetMessagePattern函数定义格式,并使用qFormatLogMessage函数格式化输出值写入文件中。

二、日志文件输出的相关理解

1.Qt日志输出函数参数分析

下方是日志输出程序的函数格式,参数分别是消息类型、消息上下文信息、消息原数据

cpp 复制代码
void myMessageOutput(**QtMsgType type**, **const QMessageLogContext &context**, **const QString &msg**)
  1. QtMsgType type:消息类型,可根据传入的类型数据通过判断做出不同操作,以下是类型枚举。
cpp 复制代码
enum QtMsgType { QtDebugMsg, QtWarningMsg, QtCriticalMsg, QtFatalMsg, QtInfoMsg, QtSystemMsg = QtCriticalMsg }
  1. const QMessageLogContext &context:输出数据上下文信息,该对象包含输出数据的版本、输出行号、输出函数名、输出文件名、输出类别(此处类别值得不是QtMsgType的类型)。
  2. const QString &msg:输出函数的实际输出数据。

2.qInstallMessageHandler函数理解

指定日志输出函数(安装消息处理程序),指定的日志函数参数格式参考Qt日志输出函数参数分析

3.qSetMessagePattern函数理解

设置输出数据格式(设置消息模式),但仅限于输出到"应用程序输出"窗口中,如使用了qInstallMessageHandler,传入输出函数的数据依旧是原内容。

  1. Qt示例格式串解析
cpp 复制代码
// Qt示例格式串
#define 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}"

%{time yyyyMMdd h:mm:ss.zzz t} :时间格式化信息,以当前时间为准,该格式输出数据示例"20240503 12:40:36.989 中国标准时间 "。
%{if-debug}D%{endif}%{if-info}I%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif} :根据输出类型输出不同的数据信息。
%{file} :输出数据的实际文件名
%{line} :输出数据的实际行号
%{message}:输出数据的原数据

  1. Qt自带的参数占位符
占位符 释义
%{appname} 应用程序名称,受pro文件中的TARGET和QApplication::setApplicationName(优先级更高)的影响
%{category} 日志类别
%{file} 输出调用的文件名
%{function} 输出调用的所在函数
%{line} 输出调用的所在行
%{message} 输出实际信息
%{pid} 输出进程的pid(QCoreApplication::applicationPid())
%{threadid} 输出线程的线程id
%{qthreadptr} 输出线程的线程指针(QThread::currentThread()的结果)
%{type} 输出类型:warning debug info critical fatal
%{time process} 进程运行的时间(自进程启动以来的秒数)
%{time boot} 计算机Boot启动时间的时间戳(ms)
%{time [format]} 时间信息(带格式化信息)
%{backtrace [depth=N] } 暂略:此扩展仅在某些平台上可用(目前仅在使用glibc的平台上可用)

4.qFormatLogMessage函数理解

格式化日志信息, 根据qSetMessagePattern函数定义的规则格式化传入的日志信息,建议在qInstallMessageHandler指定的日志输出函数中使用

三、源码

main.cpp

cpp 复制代码
#include "mainwindow.h"

#include <QApplication>

#include <QDebug>
#include <QFile>
#include <qlogging.h>

#define TYPE_FLAG 1

#if 1 == TYPE_FLAG
    #define OUTPUT_QT_HELP_EXAMPLE      // Qt帮助示例输出
#elif 2 == TYPE_FLAG
    #define OUTPUT_PURE_EXAMPLE         // 纯净输出(不夹带任何格式,日志所见即所得)
#elif 3 == TYPE_FLAG
    #define OUTPUT_FORMAT_QT_EXAMPLE    // 格式化输出到Qt程序输出栏中
#elif 4 == TYPE_FLAG
    #define OUTPUT_FORMAT_FILE_EXAMPLE  // 格式化输出到指定输出文件中
#endif

QString g_fileName;

#define 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帮助示例源码
void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg);

//! 纯净输出
void myMessageOutputForPure(QtMsgType type, const QMessageLogContext &context, const QString &msg);

//! 格式输出到Qt程序输出栏
void myMessageOutputForQtConsole(QtMsgType type, const QMessageLogContext &context, const QString &msg);

//! 格式输出到指定文件中
void myMessageOutputForFile(QtMsgType type, const QMessageLogContext &context, const QString &msg);

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

#ifdef OUTPUT_QT_HELP_EXAMPLE //! Qt帮助示例输出
    // 指定日志输出函数(安装消息处理程序)
    qInstallMessageHandler(myMessageOutput);
#elif defined(OUTPUT_PURE_EXAMPLE) //! 纯净输出(不夹带任何格式,日志所见即所得)
    g_fileName = "myMessageOutputForPure.log";
    // 指定日志输出函数(安装消息处理程序)
    qInstallMessageHandler(myMessageOutputForPure);
#elif defined(OUTPUT_FORMAT_QT_EXAMPLE) //! 格式化输出到Qt程序输出栏中
    g_fileName = "myMessageOutputForQtConsole.log";
    // 设置输出数据格式(设置消息模式)
    qSetMessagePattern(QT_MESSAGE_PATTERN);
    // 指定日志输出函数(安装消息处理程序)
    qInstallMessageHandler(myMessageOutputForQtConsole);
#elif defined(OUTPUT_FORMAT_FILE_EXAMPLE) //! 格式化输出到指定输出文件中
    g_fileName = "myMessageOutputForFile.log";
    // 设置输出数据格式(设置消息模式)
    qSetMessagePattern(QT_MESSAGE_PATTERN);
    // 指定日志输出函数(安装消息处理程序)
    qInstallMessageHandler(myMessageOutputForFile);
#endif

    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

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  %s)\n", localMsg.constData(), file, context.line, function, context.category);
        break;
    case QtInfoMsg:
        fprintf(stderr, "Info: %s (%s:%u, %s  %s)\n", localMsg.constData(), file, context.line, function, context.category);
        break;
    case QtWarningMsg:
        fprintf(stderr, "Warning: %s (%s:%u, %s  %s)\n", localMsg.constData(), file, context.line, function, context.category);
        break;
    case QtCriticalMsg:
        fprintf(stderr, "Critical: %s (%s:%u, %s  %s)\n", localMsg.constData(), file, context.line, function, context.category);
        break;
    case QtFatalMsg:
        fprintf(stderr, "Fatal: %s (%s:%u, %s  %s)\n", localMsg.constData(), file, context.line, function, context.category);
        break;
    }
}

void myMessageOutputForPure(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    QByteArray localMsg = msg.toLocal8Bit();
    QFile file(g_fileName);
    if(file.open(QIODevice::Append)) {
        file.write(localMsg + "\n\n");
        file.close();
    }
}

void myMessageOutputForQtConsole(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    QByteArray localMsg = msg.toLocal8Bit();
    QFile file(g_fileName);
    if(file.open(QIODevice::Append)) {
        file.write(localMsg + "\n\n");
        file.close();
    }
}

void myMessageOutputForFile(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    QFile file(g_fileName);
    if(file.open(QIODevice::Append)) {
        file.write(qFormatLogMessage(type, context, msg).toLocal8Bit() + "\n\n");
        file.close();
    }
}

mainwindow

mainwindow.h

cpp 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    /**
     * @brief on_btnQDebug_clicked 调试信息
     */
    void on_btnQDebug_clicked();

    /**
     * @brief on_btnQInfo_clicked 普通信息
     */
    void on_btnQInfo_clicked();

    /**
     * @brief on_btnQWarning_clicked 一般警告
     */
    void on_btnQWarning_clicked();

    /**
     * @brief on_btnQCritical_clicked 严重错误
     */
    void on_btnQCritical_clicked();

    /**
     * @brief on_btnQFatal_clicked 致命错误
     */
    void on_btnQFatal_clicked();

    /**
     * @brief on_btnCancelOutputFile_clicked取消输出文件
     */
    void on_btnCancelOutputFile_clicked();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

mainwindow.cpp

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QDebug>
#include <QElapsedTimer>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_btnQDebug_clicked()
{
    static int cntFlag = 0;
    qDebug() << u8"调试信息输出 qDebug" << ++cntFlag;
}

void MainWindow::on_btnQInfo_clicked()
{
    static int cntFlag = 0;
    qInfo() << u8"普通信息输出 qInfo" << ++cntFlag;
}

void MainWindow::on_btnQWarning_clicked()
{
    static int cntFlag = 0;
    qWarning() << u8"一般警告输出 qWarning" << ++cntFlag;
}

void MainWindow::on_btnQCritical_clicked()
{
    static int cntFlag = 0;
    qCritical() << u8"严重错误输出 qCritical" << ++cntFlag;
}

void MainWindow::on_btnQFatal_clicked()
{
    static int cntFlag = 0;
    qFatal(QString(u8"致命错误输出 qFatal %1").arg(++cntFlag).toStdString().data() ) ;
}

void MainWindow::on_btnCancelOutputFile_clicked()
{
    qInstallMessageHandler(Q_NULLPTR);
    ui->btnCancelOutputFile->setEnabled(false);
}

mainwindow.ui

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>283</width>
    <height>146</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
     <widget class="QPushButton" name="btnCancelOutputFile">
      <property name="text">
       <string>取消输出输出日志</string>
      </property>
     </widget>
    </item>
    <item>
     <layout class="QGridLayout" name="gridLayout">
      <item row="0" column="0">
       <spacer name="horizontalSpacer">
        <property name="orientation">
         <enum>Qt::Horizontal</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>31</width>
          <height>20</height>
         </size>
        </property>
       </spacer>
      </item>
      <item row="0" column="1" colspan="2">
       <widget class="QPushButton" name="btnQDebug">
        <property name="text">
         <string>QDebug</string>
        </property>
       </widget>
      </item>
      <item row="0" column="3" colspan="2">
       <widget class="QPushButton" name="btnQInfo">
        <property name="text">
         <string>QInfo</string>
        </property>
       </widget>
      </item>
      <item row="0" column="5">
       <spacer name="horizontalSpacer_2">
        <property name="orientation">
         <enum>Qt::Horizontal</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>32</width>
          <height>20</height>
         </size>
        </property>
       </spacer>
      </item>
      <item row="1" column="0" colspan="2">
       <widget class="QPushButton" name="btnQWarning">
        <property name="text">
         <string>QWarning</string>
        </property>
       </widget>
      </item>
      <item row="1" column="2" colspan="2">
       <widget class="QPushButton" name="btnQCritical">
        <property name="text">
         <string>QCritical</string>
        </property>
       </widget>
      </item>
      <item row="1" column="4" colspan="2">
       <widget class="QPushButton" name="btnQFatal">
        <property name="text">
         <string>QFatal</string>
        </property>
       </widget>
      </item>
     </layout>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>283</width>
     <height>23</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

友情提示------哪里看不懂可私哦,让我们一起互相进步吧

(创作不易,请留下一个免费的赞叭 谢谢 ^o^/)

注:文章为作者编程过程中所遇到的问题和总结,内容仅供参考,若有错误欢迎指出。

注:如有侵权,请联系作者删除

相关推荐
一点媛艺3 小时前
Kotlin函数由易到难
开发语言·python·kotlin
姑苏风3 小时前
《Kotlin实战》-附录
android·开发语言·kotlin
奋斗的小花生4 小时前
c++ 多态性
开发语言·c++
魔道不误砍柴功4 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
闲晨4 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
老猿讲编程5 小时前
一个例子来说明Ada语言的实时性支持
开发语言·ada
Chrikk6 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*6 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue6 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man6 小时前
【go从零单排】go语言中的指针
开发语言·后端·golang