Qt开发之路60---Qt日志重定向之输出Log至文件或UI控件上

一:介绍

软件里面的打印信息,通过日志记录到文件或者输出到控件上,方便查看。

二:调试信息

Qt有Debug、Warning、Info、Critical、Fatal五种级别的调试信息。

  • qDebug--------调试信息
  • qWarning--------警告信息
  • qInfo--------警告信息
  • qCritical--------严重错误
  • qFatal--------致命错误

三:调试消息重定向

Qt4提供了qInstallMsgHandler函数
Qt5提供了qInstallMessageHandler函数
对qDebug、qWarning、qCritical、qFatal等函数输出信息的重定向处理。

四:实现方法

1.qInstallMessageHandler函数注册回调函数:

void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)

2.myMessageOutput函数里面实现log信息的输出。

五:例程1:输出到log文件

1.main函数中通过qInstallMessageHandler注册回调函数
2.在myMessageOutput函数中把调试信息写入到文件中

#include "mainwindow.h"
#include 
#include 
#include 
#include 
#include 


QMutex mutex;

void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
	
	//创建log文件夹
    QDir dir("log");
    if (!dir.exists())
    {
         QDir dir;
         dir.mkdir("log");
    }

	//创建log文件
    QString currentDate = QDateTime::currentDateTime().toString("yyyyMMdd");
    QString logName = "log" + currentDate + ".txt";
    QString logFileName = "log/" + logName;


    // 加锁
    mutex.lock();

    QByteArray localMsg = msg.toLocal8Bit();

	//信息分类
    QString strMsg("");
    switch(type)
    {
    case QtDebugMsg:
        strMsg = QString("Debug:");
        break;
    case QtInfoMsg:
        strMsg = QString("Info:");
        break;
    case QtWarningMsg:
        strMsg = QString("Warning:");
        break;
    case QtCriticalMsg:
        strMsg = QString("Critical:");
        break;
    case QtFatalMsg:
        strMsg = QString("Fatal:");
        break;

        default:
            break;
    }


    //Release 版本默认不包含context这些信息:文件名、函数名、行数,需要在.pro项目文件加入以下代码,加入后最好重新构建项目使之生效:
    //DEFINES += QT_MESSAGELOGCONTEXT

    //在.pro文件定义以下的宏,可以屏蔽相应的日志输出
    //DEFINES += QT_NO_WARNING_OUTPUT
    //DEFINES += QT_NO_DEBUG_OUTPUT
    //DEFINES += QT_NO_INFO_OUTPUT


	//文件名、函数名、行数
    strMsg += QString("Function: %1  File: %2  Line: %3 ").arg(context.function).arg(context.file).arg(context.line);

    // 时间和内容
    QString strDateTime = QDateTime::currentDateTime().toString("hh:mm:ss");
    QString strMessage = QString("%1 %2:%3").arg(strDateTime).arg(strMsg).arg(localMsg.constData());



	//写入文件
    QFile file(logFileName);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Append))
    {
        file.close();
        return ;
    }
    QTextStream stream(&file);
    stream << strMessage << "\r\n";;
    file.flush();
    file.close();


    // 解锁
    mutex.unlock();

}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    qInstallMessageHandler(myMessageOutput);
	
	//测试
	qDebug("This is a debug test message.");

    return a.exec();
}

六:例程2:输出到UI控件上

1.main函数中通过qInstallMessageHandler注册回调函数
2.在myMessageOutput函数中把调试信息通过appendMsgOut()发送到主窗口MainWindow

#include "mainwindow.h"
#include 
#include 
#include 
#include 
#include 



MainWindow *pw = nullptr;
QMutex mutex;

void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    // 加锁
    mutex.lock();

    QByteArray localMsg = msg.toLocal8Bit();

	//信息分类
    QString strMsg("");
    switch(type)
    {
    case QtDebugMsg:
        strMsg = QString("Debug:");
        break;
    case QtInfoMsg:
        strMsg = QString("Info:");
        break;
    case QtWarningMsg:
        strMsg = QString("Warning:");
        break;
    case QtCriticalMsg:
        strMsg = QString("Critical:");
        break;
    case QtFatalMsg:
        strMsg = QString("Fatal:");
        break;

        default:
            break;
    }



    // 设置输出信息格式
    QString strDateTime = QDateTime::currentDateTime().toString("hh:mm:ss");
    QString strMessage = QString("%1 %2:%3").arg(strDateTime).arg(strMsg).arg(localMsg.constData());

    // 输出信息到UI
    pw->appendMsgOut(strMessage);


    // 解锁
    mutex.unlock();

}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    qInstallMessageHandler(myMessageOutput);


	//主窗口
    MainWindow w;

    pw = &w;

    w.show();

    return a.exec();
}

3.在MainWindow中实现信息输出到控件上,注意多线程操作Ui时要用信号,不然容易卡死界面

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void appendMsgOut(QString msg);

signals:
    void sglAppendText(QString);


private:
    Ui::MainWindow *ui;
  
};

#endif // MAINWINDOW_H

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include 
#include 


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

	//打印信息到textEdit控件上
    ui->textEdit_msgOut->document()->setMaximumBlockCount(100);
    connect(this,SIGNAL(sglAppendText(QString)),ui->textEdit_msgOut,SLOT(append(QString)));

}

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



void MainWindow::appendMsgOut(QString msg)
{
    if(msg.contains("Debug:")){
        msg = "" + msg + " ";
    }else if (msg.contains("Info:")) {
        msg = "" + msg + " ";
    }else if (msg.contains("Warning:")) {
        msg = "" + msg + " ";
    }else if (msg.contains("Critical:")) {
        msg = "" + msg + " ";
    }else if (msg.contains("Fatal:")) {
        msg = "" + msg + " ";
    }else {
        msg = "" + msg + " ";
    }

    //不同线程直接调用会导致程序崩溃,改用信号槽的方式
    //ui->textEdit_msgOut->append(msg);


    emit sglAppendText(msg);

}

你可能感兴趣的:(Qt,qt,ui)