QT日志库:log4Qt及Qt自带日志库使用

介绍

  Log4Qt是使用Trolltech Qt Framework的Apache Software Foundation Log4j包的C ++端口。它旨在供开源和商业Qt项目使用。所以 Log4Qt 是Apache Log4J 的Qt移植版,所以看Log4J的资料应该是最直接有效的(因为 Log4Qt的直接资料太少了)。

  Log4Qt主要是用来记录日志(有助于程序调试)。有3个主要的组件:

1、Logger

  提供日志记录服务,可以有多个Logger存在,每个有它们自己的名字。Logger间存在隶属关系,有一个Logger称为根Logger。

2、Appender

  用来指明将日志记录到什么地方:比如,控制台、文件、数据库,等等

3、Layout

  控制日志的输出格式,可以类比一下C中的printf哈。

下载log4qt源码
源码下载

当前最新版本为log4qt-0.3.zip,这源码包最后修改日期为2009年3月1日。
Sourceforge 下载地址:

https://sourceforge.net/projects/log4qt/
或者

https://github.com/devbean/log4qt

或者

https://gitee.com/mirrors/log4qt

编译为动态库

使用qtCreater打开pro文件:文件路径:qt_log\log4qt\tests\log4qttest.pro

Qt4版本日志移植到qt5编译过程出现错误

错误一:识别QtMsgHandler类

“error: 'QtMsgHandler' does not name a type”

错误二:QObject类未声明

点击跳转到错误文件,添加QObject

错误三:QTextCodec编码错误

错误四:操作符“<<”歧义

错误五:qInstallMsgHandle未声明

 错误六:Qt编译错误: 'UnicodeUTF8' is not a member of 'QApplication'

错误七:error: undefined reference to `vtable for

原因:

 子类没有实现父类的纯虚函数;在Qt中,首先要想到的是在一个类中添加了新的继承QObject,并添加了 Q_OBJECT 宏,然后执行构造或重新构造,都会造成这个错误。根本原因是,只执行构造或重新构造,都不会编译新添加的宏Q_OBJECT。因此在这之前要执行qmake让moc编译器去预编译Q_OBJECT然后再执行构造&#xff0c;就不再报错了。

项目使用

pro文件中添加

#log start
LIBS +=-LD:\C++\plugins\dll/ -lhlog4qt1
INCLUDEPATH +=D:\C++\plugins\include
#log end

main.cpp


    /* 根据指定的日志配置文件初始化日志 */
    Log4Qt::PropertyConfigurator::configure( "./mylog.conf");

    Log4Qt::Logger *mylog1 = Log4Qt::Logger::logger("Mylog1");
    /* 处理qt调试输出信息,将qDebug之类的信息重定向到日志文件 */
    Log4Qt::LogManager::setHandleQtMessages(true);

    /* 日志输出 */
    mylog1->debug("log debug");
    mylog1->info("log info");
    mylog1->warn("log warn");
    mylog1->error("log error");
    mylog1->fatal("log fatal");



    qDebug("qDebug");
    qInfo("qInfo");
    qWarning("qWarning");
    qCritical("qCritical");
    qFatal("qCritical");
    qDebug()<<"qDebug()";

QT自带日志库


#include <QMutex>
#include <QMutexLocker>
#include <QFile>
#include <QTextStream>
#include <QMessageLogContext>

class SaveLog
{
public:
    static SaveLog* Instance()
    {
        static SaveLog instance;
        return &instance;
    }

    bool getUseContext() const { return useContext; }
    void setUseContext(bool value) { useContext = value; }

    void save(const QString &log)
    {
        // 将日志内容保存到文件
        QFile file("log.txt");
        if (file.open(QIODevice::Append)) {
            QTextStream out(&file);
            out << log << "\n";
            file.close();
        }
    }

private:
    SaveLog() : useContext(true) {}
    bool useContext;
};

// 日志处理函数
void Log(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    static QMutex mutex;
    QMutexLocker locker(&mutex);
    QString content;

    switch (type) {
        case QtDebugMsg:
        case QtInfoMsg:
            content = QString("Debug/Info: %1").arg(msg);
            break;
        case QtWarningMsg:
            content = QString("Warning: %1").arg(msg);
            break;
        case QtCriticalMsg:
            content = QString("Critical: %1").arg(msg);
            break;
        case QtFatalMsg:
            content = QString("Fatal: %1").arg(msg);
            break;
    }

#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
    if (SaveLog::Instance()->getUseContext() && context.line != -1) {
        content = QString("%1 (%2, %3, %4)")
                  .arg(content)
                  .arg(context.file)
                  .arg(context.line)
                  .arg(context.function);
    }
#endif

    SaveLog::Instance()->save(content);
}

// 安装日志钩子
void start()
{
    qInstallMessageHandler(Log);

}
// 卸载日志钩子
void stop()
{
    qInstallMessageHandler(nullptr);
}

使用


    start();
    qDebug()<<"hehe";
    qInfo()<<"你好";
    qWarning()<<"finish";
    qCritical()<<"critical";
//    qFatal("fatal");
    qDebug()<<"ttt";

    stop();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/897420.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DCS项目调试踩坑记录

最近在调试一个DCS项目&#xff08;集散控制系统&#xff09;&#xff0c;实际上就是一个新建厂区的控制系统。PLC用的是西门子1500&#xff0c;控制画面使用组态王7.5。 在调试过程中&#xff0c;发现给西门子DB块的变量转移到组态王太难了&#xff0c;因此记录一下&#xff0…

【IEEE独立出版 | 厦门大学主办】第四届人工智能、机器人和通信国际会议(ICAIRC 2024)

第四届人工智能、机器人和通信国际会议&#xff08;ICAIRC 2024&#xff09;定于2024年12月27-29日在中国厦门举行。会议旨在为从事“人工智能、机器人和通信”研究的专家学者、工程技术人员、技术研发人员提供一个共享科研成果和前沿技术&#xff0c;了解学术发展趋势&#xf…

TCRT5000红外循迹传感器指南

开始先发送红外线 当返回的红外线的信号量小于规定值时&#xff0c;D0输出0&#xff0c;反之输出1 黑色的物体吸收红外光比其他物体多&#xff0c;所以检测到黑色物体D0会输出0,可以以此来循迹 逆时针调节电位器可以使得规定值上升&#xff0c;需要接受更多信号才能输出1 顺…

【前端】如何制作一个自己的网页(15)

有关后代选择器的具体解释&#xff1a; 后代选择器 后代选择器使用时&#xff0c;需要以空格将多个选择器间隔开。 比如&#xff0c;这里p span&#xff0c;表示只设置p元素内&#xff0c;span元素的样式。 <style> /* 使用后代选择器设置样式 */ p span { …

大数据-184 Elasticsearch - 原理剖析 - DocValues 机制原理 压缩与禁用

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

数字后端零基础入门系列 | Innovus零基础LAB学习Day4

Module 10 利用Global Router来分析设计是否可绕通 LAB10-1 跑一个placement 本章节目的是load进一个floorplan&#xff0c;跑通一个placement并完成post-placement的timing优化 导入设计和floorplan 这步之前的lab已经做过了&#xff0c;大家再按照下面的步骤再练习巩固下…

信息安全工程师(62)网络蠕虫分析与防护

网络蠕虫分析 网络蠕虫是一种智能化、自动化&#xff0c;综合了网络攻击、密码学和计算机病毒技术的恶意程序或代码&#xff0c;它无须计算机使用者干预即可运行。这种蠕虫能够扫描和攻击网络上存在系统漏洞的节点主机&#xff0c;并通过局域网或国际互联网从一个节点传播到另一…

【UE5】通过程序化网格体组件实现剖切功能

效果 步骤 1. 新建两个Actor类蓝图&#xff0c;分别命名为“BP_CutActor”、“BP_CutPlane”&#xff0c;分别表示被剖切的网格体和剖切的片面。 2. 打开“BP_CutActor”&#xff08;被剖切的网格体&#xff09;&#xff0c;添加静态网格体组件、程序化网格体组件&#xff0c;…

(三)第一个Qt程序“Qt版本的HelloWorld”

一、随记 我们在学习编程语言的时候&#xff0c;各种讲解编程语言的书籍中通常都会以一个非常经典的“HelloWorld”程序展开详细讲解。程序虽然简短&#xff0c;但是“麻雀虽小&#xff0c;五脏俱全”&#xff0c;但是却非常适合用来熟悉程序结构、规范&#xff0c;快速形成对编…

原型模式和建造模式的区别

原型模式&#xff08;Prototype Pattern&#xff09;和建造者模式&#xff08;Builder Pattern&#xff09;虽然都是创建型设计模式&#xff0c;但它们的应用场景和实现方式有着显著的区别。以下是二者的详细对比&#xff1a; 1. 意图和应用场景 原型模式&#xff1a; 意图&a…

【论文阅读】2022 TChecker Precise Static Inter-Procedural Analysis for Detecting

总览 “TChecker: Precise Static Inter - Procedural Analysis for Detecting Taint - Style Vulnerabilities in PHP Applications” 由香港中文大学的 Changhua Luo、Penghui Li 和 Wei Meng 撰写。论文介绍了 TChecker 工具&#xff0c;用于检测 PHP 应用中的污点式漏洞&am…

【Linux】为什么环境变量具有全局性?共享?写时拷贝优化?

环境变量表具有全局性的原因&#xff1a; 环境变量表之所以具有全局性的特征&#xff0c;主要是因为它们是在进程上下文中维护的&#xff0c;并且在大多数操作系统中&#xff0c;当一个进程创建另一个进程&#xff08;即父进程创建子进程&#xff09;时&#xff0c;子进程会继承…

动态路由:RIP实验

1.划分IP 2.配置环回 3.接口配置IP地址 4.进入RIP中&#xff0c;关闭手工汇总&#xff0c;选择版本号&#xff0c;宣告 5.ping命令查看是否全网通 6.在R3上配置缺省路由 [R3-rip-1]default-route originate 在边界路由器上下发缺省 7.为了安全配置手工认证 [R1-Gigab…

qt QVariant详解

QVariant是Qt框架中一个功能强大的变体类&#xff0c;它提供了一种通用的方式来存储Qt对象及其他类的值&#xff0c;能够以类似于指针的方式存储任意类型的值。 一、 主要特性 通用性&#xff1a;QVariant可以存储几乎所有数据类型&#xff0c;包括基本数据类型&#xff08;如…

刷题小记9:回溯

回溯算法模板&#xff1a; void backtracking(参数) {if (终止条件) {存放结果;return;}for (选择&#xff1a;本层集合中元素&#xff08;树中节点孩子的数量就是集合的大小&#xff09;) {处理节点;backtracking(路径&#xff0c;选择列表); // 递归回溯&#xff0c;撤销处理…

html+vue实现动态复杂table

1、效果 2、代码 <div style"overflow: scroll; width: 100%;height: calc(100% - 80px);"><table class"table table-bordered" style"width: auto;table-layout: fixed;"><thead style"position: sticky;top: -1px;z-inde…

【C++干货篇】——类和对象的魅力(四)

【C干货篇】——类和对象的魅力&#xff08;四&#xff09; 1.取地址运算符的重载 1.1const 成员函数 将const修饰的成员函数称之为const成员函数&#xff0c;const修饰成员函数放到成员函数参数列表的后面。const实际修饰该成员函数隐含的this指针&#xff08;this指向的对…

IDEA如何查看所有的断点(Breakpoints)并关闭

前言 我们在使用IDEA开发Java应用时&#xff0c;基本上都需要进行打断点的操作&#xff0c;这方便我们排查BUG&#xff0c;也方便我们查看设计的是否正确。 不过有时候&#xff0c;我们不希望进入断点&#xff0c;这时候除了点击断点关闭外&#xff0c;有没有更快速的方便关闭…

深入浅出剖析重量级文生图模型Flux.1

24年8月&#xff0c;Flux.1的发布又一次火爆整个AI绘图领域&#xff0c; 号称AI文生图的“新标杆”&#xff0c;刷新AI图像领域的新格局。 Flux是一款由Black Forest Labs开发的尖端AI图像生成工具&#xff0c;旨在通过先进的技术将文本提示转化为高质量的图像。Flux AI支持多…

利用 OBS 推送 WEBRTC 流到 smart rtmpd

webrtc whip 推流 & whep 拉流简介 RFC 定义 通用的 webrtc 对于 SDP 协议的交换已经有对应的 RFC 草案出炉了。这就是 WHIP( push stream ) & WHEP ( pull stream ) . WHIP RFC Link: https://www.ietf.org/archive/id/draft-ietf-wish-whip-01.html WHEP RFC Link:…