通过qInstallMessageHandler获取Qt的打印信息,将这些打印信息存放到一个Widget中,实现不通过后台就能查看日志信息。
实现方法如下:
main.cpp
#include "mainwidget.h"
#include <QApplication>
#include <QStyleFactory>
#include "logwidget.h"
void logOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
LogWidget::instance()->myMessageOutput(type,context,msg);
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QApplication::setStyle(QStyleFactory::create("Fusion"));
bool ok = false;
QSharedMemory sharedMemory("testApp");
if (sharedMemory.attach(QSharedMemory::ReadOnly))
{
sharedMemory.detach();
}
if (sharedMemory.create(1))
{
LogWidget::instance()->show();
qInstallMessageHandler(logOutput);
MainWidget w;
w.move(0,0);
w.show();
ok = a.exec();
if (sharedMemory.isAttached())
sharedMemory.detach();
}
return ok;
}
以下代码中记录了前台、后台、文件查看调试信息
logwidget.cpp
#include "logwidget.h"
#include <QDateTime>
#include <QApplication>
#include <QDir>
#include <QTextStream>
#include <QHBoxLayout>
QMutex LogWidget::m_mutex;
LogWidget* LogWidget::m_Instance = nullptr;
LogWidget::LogWidget(QWidget *parent) :
QWidget(parent)
{
this->setWindowFlags(Qt::WindowStaysOnTopHint|Qt::WindowCloseButtonHint|Qt::WindowMaximizeButtonHint);
m_textEdit = new QTextEdit(this);
QHBoxLayout* lay = new QHBoxLayout(this);
lay->addWidget(m_textEdit);
this->setLayout(lay);
connect(this,&LogWidget::sig_logUpdate,this,[&](QString msg)
{
m_textEdit->append(msg);
});
}
LogWidget::~LogWidget()
{
}
LogWidget *LogWidget::instance()
{
if (m_Instance == NULL)
{
m_mutex.lock();
if (m_Instance == NULL)
{
m_Instance = new LogWidget();
}
m_mutex.unlock();
}
return m_Instance;
}
void LogWidget::myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
#if 1
// 加锁
static QMutex mutex;
mutex.lock();
QByteArray localMsg = msg.toLocal8Bit();
QString strMsg("");
switch(type)
{
case QtDebugMsg:
strMsg = QString("Debug:");
break;
case QtWarningMsg:
strMsg = QString("Warning:");
break;
case QtCriticalMsg:
strMsg = QString("Critical:");
break;
case QtFatalMsg:
strMsg = QString("Fatal:");
break;
}
// 设置输出信息格式
QString strDateTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
QString strMessage = QString("DateTime:%1:%2 \t\t(line:%3) (File:%4)").arg(strDateTime)
.arg(localMsg.constData()).arg(context.line).arg(context.file);
//打印输出窗口显示调试信息
fprintf(stderr, "%s\n", strMessage.toLatin1().data());
//前台Widget显示调试信息
emit sig_logUpdate(strMessage);
// 输出调试信息至文件中(读写、追加形式)
QDir dir(QApplication::applicationDirPath()+"/log");
if (!dir.exists())
dir.mkpath(dir.path());
QString logName = dir.path() + "/log_"+QDate::currentDate().toString("yyyy-MM-dd")+".txt";
QFile file(logName);
file.open(QIODevice::ReadWrite | QIODevice::Append);
QTextStream stream(&file);
stream << strMessage << "\r\n";
file.flush();
file.close();
// 解锁
mutex.unlock();
#endif
}
logwidget.h
#ifndef LOGWIDGET_H
#define LOGWIDGET_H
#include <QWidget>
#include <QTextEdit>
#include <QMutex>
class LogWidget : public QWidget
{
Q_OBJECT
public:
~LogWidget();
static LogWidget *instance();
void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg);
signals:
void sig_logUpdate(QString msg);
private:
explicit LogWidget(QWidget *parent = nullptr);
static QMutex m_mutex;
static LogWidget* m_Instance;
QTextEdit* m_textEdit = nullptr;
};
#endif // LOGWIDGET_H