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

yumo6665个月前 (08-18)技术文章123

1、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());
}

2、qDebug() 自定义类输出

2.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.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;
}

2.3、调用

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

    qDebug() << my_class;
}

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

QT开发交流+赀料君羊:714620761

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

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

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

定义相关的变量和接口

关键代码如下(示例):

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);

运行结果图

相关文章

Qt多线程创建(qt多线程直接处理数据)

【为什么要用多线程?】传统的图形用户界面应用程序都只有一个执行线程,并且一次只执行一个操作。如果用户从用户界面中调用一个比较耗时的操作,当该操作正在执行时,用户界面通常会冻结而不再响应。这个问题可以用...

正点原子I.MX6U嵌入式Qt开发指南:第十章《多线程》

今日头条/西瓜视频/抖音短视频 同名:正点原子原子哥今日头条/西瓜视频/抖音短视频账号:正点原子-原子哥感谢各位的关注和支持,你们的关注和支持是正点原子无限前进的动力。第十章《多线程》我们写的一个应用...

从零开始学Qt(76):什么是多线程?(怎么从0开始学编程)

多线程程序一个应用程序一般只有一个线程,一个线程内的操作是顺序执行的,如果有某个比较消耗时 间的计算或操作,比如网络通信中的文件传输,在一个线程内操作时,用户界面就可能会冻结而不能及时响应。这种情况下...

基于Qt多线程实现UDP通信(qt实现多线程文件传输)

# 演示先演示,在展开如何实现,本次代码在windows、linux、mac都可使用。大家不能光看,实际敲一敲,敲出强大,敲出好工作。简单理解:服务器-》发送hello-》客户端也可以不写客户端或者服...

C++ Qt开发:运用QThread多线程组件

阅读目录1.1 线程组与多线程1.2 向线程中传递参数1.3 互斥同步线程锁1.4 读写同步线程锁1.5 基于信号线程锁Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,...

Qt使用OpenGL进行多线程离屏渲染(opengl版本过低怎么办)

基于Qt Widgets的Qt程序,控件的刷新默认状况下都是在UI线程中依次进行的,换言之,各个控件的QWidget::paintEvent方法会在UI线程中串行地被调用。若是某个控件的paintEv...