Qt-QDebug格式输出、自定义类输出及重定向输出Log


一、qDebug() 格式化输出

qDebug格式化支持printf的格式化标识符
如果向函数传递格式字符串和参数列表,它的工作方式类似于C printf()函数。 格式应该是Latin-1字符串。

格式化demo

代码如下(示例):

void Widget::Printf() {
    
    
    QString str = "qwe";
    QDateTime dt = QDateTime::fromTime_t(time(NULL));
    qreal pi = 3.141592653589793;
    QString str_pi = QString::number(pi, 'g', 16);

    // 格式化输出
    qDebug("this is %s, Today is %04d-%02d-%02d, PI = %s", str.toLocal8Bit().data(), dt.date().year(),
           dt.date().month(), dt.date().day(), str_pi.toLocal8Bit().data());
}

二、qDebug() 自定义类输出

1.重载操作符 << 放在与类声明的头文件中, 在类的声明外部

mycalss类的头文件

代码如下(示例):

#ifndef MYCLASS_H
#define MYCLASS_H
#include <QDebug>
#include <QString>

class MyClass {
    
    
public:
    MyClass();

    int Get_Id() const {
    
    return _id;}
    QString Get_Name() const {
    
    return _name;}

private:
    int _id = 1;
    QString _name = "qwe";
};

QDebug operator<<(QDebug debug, const MyClass &my_class);

#endif // MYCLASS_H

mycalss类的源文件

代码如下(示例):

#include "myclass.h"

MyClass::MyClass() {
    
    

}


QDebug operator<<(QDebug debug, const MyClass &my_class) {
    
    
    debug << "Id =" << my_class.Get_Id() << "name =" << my_class.Get_Name();
    return debug;
}

2.重载操作符 << 友元函数声明

mycalss类的头文件

代码如下(示例):

#ifndef MYCLASS_H
#define MYCLASS_H
#include <QDebug>
#include <QString>

class MyClass {
    
    
protected:
    friend QDebug operator<<(QDebug debug, const MyClass &my_class);
    
public:
    MyClass();

    int Get_Id() const {
    
    return _id;}
    QString Get_Name() const {
    
    return _name;}

private:
    int _id = 1;
    QString _name = "qwe";
};
#endif // MYCLASS_H

mycalss类的源文件

代码如下(示例):

#include "myclass.h"

MyClass::MyClass() {
    
    

}
QDebug operator<<(QDebug debug, const MyClass &my_class) {
    
    
    debug << "Id =" << my_class._id << "name =" << my_class._name;
    return debug;
}

3.调用

void Widget::Printf_Class() {
    
     // 自定义类输出到qDebug
    MyClass my_class;

    qDebug() << my_class;
}

三、qDebug() 输出重定向 LOG 文件

多线程输出是需要考虑线程安全问题

QMutex 互斥量:QMutex类提供的是线程之间的访问顺序化。QMutex的目的是保护一个对象、数据结构或者代码段,所以同一时间只有一个线程可以访问它。

QMutexLocker 类:使用该类不用手动加锁释放锁,定义自动加锁,出作用于自动解锁。(RAII 资源获取即初始化)

定义相关的变量和接口

关键代码如下(示例):

扫描二维码关注公众号,回复: 13585184 查看本文章
QMutex mutex; // 为了支持多线程,需要使用锁来保护对日志文件的操作
QtMessageHandler system_default_message_handler = NULL; // 用来保存系统默认的输出接口
// 替换接口
void Custom_Message_Handler(QtMsgType type, const QMessageLogContext& context, const QString& info) {
    
    
    // 信息格式化
    QString log = QString::fromLocal8Bit("msg-[%1], file-[%2], func-[%3], category-[%4]\n")
            .arg(info).arg(context.file).arg(context.function).arg(context.category);
    bool bok = true;

    switch (type) {
    
    
    case QtDebugMsg:
        log.prepend("Qt dbg:");
        break;
    case QtWarningMsg:
        log.prepend("Qt warn:");
        break;
    case QtCriticalMsg:
        log.prepend("Qt critical:");
        break;
    case QtFatalMsg:
        log.prepend("Qt fatal:");
        break;
    case QtInfoMsg:
        log.prepend("Qt info:");
        break;
    default:
        bok = false;
        break;
    }
    if(bok) {
    
    
        // 加锁
        QMutexLocker locker(&mutex);

        QString str_file_name = "./log/log.inf";
        QString str_dir = "./log";
        QDir dir;
        dir.mkpath(str_dir);

        QFile file(str_file_name);

        if(! file.open(QFile::ReadWrite | QFile::Append)) {
    
    
            return;
        }

        file.write(log.toLocal8Bit().data());
        file.close();
    }

    if(bok) {
    
    
        // 调用系统原来的函数完成信息输出, 调试窗口
        if(NULL != system_default_message_handler) {
    
    
            system_default_message_handler(type, context, log);
        }
    }
}

在主函数进行输出重定向绑定

// 输出重定向
    system_default_message_handler = qInstallMessageHandler(Custom_Message_Handler);

完整demo下载

运行结果图

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/wct3344142/article/details/120720479