QT实时显示日志内容

性能有待提高;
能够读取指定目录下的日志文件,显示在下拉框中。
选择某一个日志之后,点击获取数据按钮,能够实时刷新日志内容。
但是每次刷新都会对整个文件进行读取,文本框重新加载文本。效率很低,影响性能。

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QList>
#include<QDir>
#include<QTime>
#include<QDateTime>
#include<QDebug>
#include<QFile>
#include<QFileSystemWatcher>

#define TIMEOUT 100
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    void getFileName(QString *path);
    void setTextBrowser(QString *path);
    //virtual void timerEvent(QTimerEvent *event);
    //int myTimerID;
    ~Widget();
signals:
    void setFileSignal();
private slots:
    void on_readBtn_clicked();

    void on_stopBtn_clicked();

    void setFileSlot();//将文件名保存到List中

    void fileUpdated(const QString &path);   // 文件被修改时调用,path是监控的路径

private:
    Ui::Widget *ui;
    QList<QString> filenames;
    QFileSystemWatcher fileSystemWatch;
};
#endif // WIDGET_H

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QString floderPath = QDir::currentPath()+"/debug/14";
    getFileName(&floderPath);
    connect(this,&Widget::setFileSignal,this,&Widget::setFileSlot);
    //布置监视文本初始化
    fileSystemWatch.addPaths(filenames);
    //qDebug()<<floderPath;

    //fileSystemWatch.thread();
    connect(&fileSystemWatch, &QFileSystemWatcher::fileChanged, this,&Widget::fileUpdated);
}

Widget::~Widget()
{
    delete ui;
    fileSystemWatch.removePaths(filenames);
}

void Widget::getFileName(QString *path)
{
    QString  LogPath = *path;//文件夹路径

    QDir dir(LogPath);

    QStringList LogList;

//向字符串列表添加文件类型,可以在此处添加过滤,只显示单日日志
    LogList << "*.log" ;
    QDateTime ct = QDateTime::currentDateTime();
    QDate dt = ct.date();
    //只看今天的
    //QString filterName = "*"+QString::number(dt.day())+".log";
    //LogList << "*" << QString::number(dt.day()) <<".log" ;
    //LogList.append(filterName);


    dir.setNameFilters(LogList);//获得文件夹下日志的名字

    int LogCount = dir.count();//获得dir里名字的个数,也表示文件夹下图片的个数

    /************获得文件名,对dir进行下标访问即可************/

    for (int i=0;i < LogCount;i++)

    {
        QString LogName  = dir[i];
        ui->comboBox->addItem(LogName);
        filenames.append(QDir::currentPath()+"/debug/14/"+LogName);
        //qDebug() << LogName;//输出文件名
    }
        qDebug() << filenames;
    //将文件名设置到下拉框
    emit setFileSignal();
}

void Widget::setTextBrowser(QString *filename){

    QString currrentfileName = QDir::currentPath()+"/debug/14/"+ui->comboBox->currentText();
    QFile file(currrentfileName);

    if(!file.isOpen()){
        file.open(QIODevice::ReadOnly);
    }
    file.flush();
    QByteArray ba = file.readAll();

    file.close();
    ui->textBrowser->setText(QString(ba));
    ui->textBrowser->reload();
    ui->textBrowser->moveCursor(QTextCursor::End);
}

void Widget::on_readBtn_clicked()
{
    setTextBrowser(NULL);
    //打开定时器
    //myTimerID=this->startTimer(TIMEOUT);


    //QFileSystemWatcher::removePaths();
    //connect(this,&QFileSystemWatcher::fileChanged,this,&Widget::setTextBrowser);

}
/*void Widget::timerEvent(QTimerEvent *event)
{
    if(event->timerId()!=myTimerID)
        return;
    setTextBrowser(NULL);
}*/

void Widget::on_stopBtn_clicked()
{
    //this->killTimer(myTimerID);
}
//通过文件字符串列表,生成文件列表,且全部打开
void Widget::setFileSlot()
{
    foreach (QString filename, filenames) {
        QFile file(filename);
        qDebug()<<filename;
    }
}
void Widget::fileUpdated(const QString &path)
{
    if(path==QDir::currentPath()+"/debug/14/"+ui->comboBox->currentText())
    {
        setTextBrowser(NULL);
    }
}

在这里插入图片描述

<think>我们参考了用户提供的三个引用,这些引用都与Qt日志处理相关。用户的需求是“实现实时打印日志的方法”。根据引用内容,核心是通过`qInstallMessageHandler`安装自定义消息处理器,将日志输出到文件或窗口等目标,并实现实时显示。 结合引用[2],我们看到一个实现方式:利用宏定义来格式化日志输出,包括时间、文件名、函数名、行号等信息。引用[3]则提到了一个函数`OutputMessage`,这可能是自定义消息处理器的实现函数。 因此,实现实时打印日志的关键步骤是: 1. 编写一个自定义的消息处理函数,该函数将接收到的日志信息实时输出(例如输出到控制台、文件或自定义的日志窗口)。 2. 使用`qInstallMessageHandler`安装这个自定义处理函数,这样Qt日志输出(如qDebug, qInfo等)就会重定向到这个函数。 3. 在自定义处理函数中,我们可以将日志信息实时显示在界面上(比如通过信号槽机制发送到UI线程的文本控件),同时也可以写入文件(按日期、大小分割,过期删除等)。 下面我们给出一个示例,展示如何自定义消息处理器并将日志实时显示在应用程序的UI界面上(假设我们有一个QPlainTextEdit控件用于显示日志): </think>### Qt实现实时打印日志的方法 在Qt中实现实时打印日志的核心是通过**自定义消息处理器**重定向日志输出,结合**信号槽机制**实现实时显示。以下是具体实现步骤: #### 1. **创建自定义消息处理器** ```cpp #include <QFile> #include <QTextStream> #include <QMutex> // 全局互斥锁防止多线程冲突 QMutex logMutex; void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { QMutexLocker locker(&logMutex); // 线程安全锁定 // 实时输出到控制台 QByteArray localMsg = msg.toLocal8Bit(); fprintf(stderr, "%s\n", localMsg.constData()); // 实时打印到stderr // 写入文件(可选) QFile logFile("app_log.txt"); if (logFile.open(QIODevice::WriteOnly | QIODevice::Append)) { QTextStream ts(&logFile); ts << QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss") << " [" << context.function << "] " << msg << "\n"; } } ``` #### 2. **安装消息处理器(在main函数中)** ```cpp int main(int argc, char *argv[]) { QApplication a(argc, argv); // 安装自定义处理器 qInstallMessageHandler(messageHandler); // [^1] // 示例日志输出 qDebug() << "调试信息: 应用程序启动"; qInfo() << "系统状态: 初始化完成"; return a.exec(); } ``` #### 3. **实现UI实时显示(关键步骤)** ```cpp // 自定义Logger类(头文件) class Logger : public QObject { Q_OBJECT public: static Logger* instance(); void log(const QString &msg); // 日志接收接口 signals: void newLog(QString msg); // 日志更新信号 private: explicit Logger(QObject *parent = nullptr); }; // 在messageHandler中触发日志信号 void messageHandler(...) { ... emit Logger::instance()->newLog(msg); // 发送实时信号 [^3] } // UI界面连接信号(如QPlainTextEdit) QObject::connect(Logger::instance(), &Logger::newLog, ui->logTextEdit, &QPlainTextEdit::appendPlainText); // [^2] ``` #### 4. **增强日志格式(可选)** ```cpp // 使用宏定义增强日志信息 [^2] #define LOG_REALTIME(msg) \ qDebug().noquote() << QString("[%1][%2:%3] %4") \ .arg(QDateTime::currentDateTime().toString("HH:mm:ss.zzz")) \ .arg(__FILE__).arg(__LINE__).arg(msg) ``` ### 技术要点解析 1. **实时性保障** - 通过`qInstallMessageHandler`接管Qt全局日志系统 - 使用`信号槽机制`跨线程更新UI(自动排队执行) - 直接输出到`stderr`保证控制台实时性 2. **线程安全设计** - `QMutex`防止多线程日志冲突 - `QMutexLocker`自动锁管理(RAII模式) 3. **扩展功能建议** - 添加日志分级过滤(DEBUG/INFO/WARN等级别) - 实现日志文件轮转(按日期/大小分割) - 增加网络传输支持(引用[2]的远程调试) > 通过此方案,所有`qDebug()`、`qInfo()`等输出将自动实时显示在UI控件中,同时保存到文件。实际应用中需注意:**信号槽连接必须使用Qt::AutoConnection**(默认),确保跨线程安全[^1][^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿波茨的鹅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值