QT:QDEBUG输出重定向和命令行参数QCommandLineParser

news2024/12/21 7:48:51

qInstallMessageHandler函数简介 

QtMessageHandler qInstallMessageHandler(QtMessageHandler handler)

        qInstallMessageHandler 是 Qt 框架中的一个函数,用于安装一个全局的消息处理函数,以替代默认的消息输出机制。这个函数允许开发者自定义 Qt 应用程序中所有调试消息、信息消息、警告消息、严重错误消息和致命错误消息的处理方式。

        当 Qt 应用程序中的任何地方调用 qDebug(), qInfo(), qWarning(), qCritical() 或 qFatal() 函数时,如果已经通过 qInstallMessageHandler 安装了一个自定义的消息处理函数,那么这个函数就会被调用,而不是将消息输出到标准输出、标准错误或其他默认位置。

自定义的消息处理函数通常具有以下签名:

void myMessageHandler(QtMsgType, const QMessageLogContext &, const QString &);

type参数:

enum QtMsgType;

 实验代码

#include <QApplication>
#include <QMutex>
#include <QMutexLocker>
#include <QFile>
#include <QDir>
#include <QDebug>
#include <QCommandLineParser>
#include <QDateTime>

static QMutex qml_logfile_mutex;
static int log_level = QtInfoMsg;
static bool g_enable_debug_time = false;
static enum QtMsgType debug_log_level = QtWarningMsg;
#define FORBID_LOG_OUTPUT_LEVEL (QtInfoMsg + 1)
#define NO_QDEBUG_LEVEL ((enum QtMsgType)(QtDebugMsg + 1))
void myMessageOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg) {
    static int file_index = 0;
    if(type < log_level){
        return;
    }
    if(type < debug_log_level){
        return;
    }
    QMutexLocker lock(&qml_logfile_mutex);

    QString filename = "";
    while (context.file != nullptr) {
        QStringList dirList;
        filename = context.file;
        if (filename.length() < 1) {
            break;
        }
        dirList = filename.split(QDir::separator());
        if (dirList.size() > 0) {
            filename = dirList[dirList.size() - 1];
        }
        if (filename.contains("/")) {
            dirList = filename.split("/");
            if (dirList.size() > 0) {
                filename = dirList[dirList.size() - 1];
            }
        }
        if (filename.contains("\\")) {
            dirList = filename.split("\\");
            if (dirList.size() > 0) {
                filename = dirList[dirList.size() - 1];
            }
        }
        break;
    };

    QString logFileFullName;
    logFileFullName = qApp->applicationDirPath();
    logFileFullName.append(QString("\\log\\console_%1.log").arg(file_index));
    QFile file(logFileFullName);
    do{
        if (!file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
            return;
        }
        if(file.pos() > 1024 * 1024){
            file.close();
            file_index++;
            QString new_file_name;
            new_file_name = qApp->applicationDirPath();
            new_file_name.append(QString("\\log\\console_%1.log").arg(file_index));
            file.setFileName(new_file_name);
            continue;
        }
        break;
    }while(1);

    QTextStream text_stream(&file);
    QString output_text;
    if(g_enable_debug_time){
        QString currentDateTime =
                QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss-zzz");
        output_text.append("[");
        output_text.append(currentDateTime);
        output_text.append("] ");
    }
    output_text.append("[");
    if (filename.length() > 0) {
        output_text.append(QString("%1").arg(type));
    }
    if (filename.length() > 0) {
        output_text.append(QString("|%1").arg(filename));
    }
    if (context.function != nullptr && strlen(context.function) > 0) {
        output_text.append(QString("|%1").arg(context.function));
    }

    if (context.line > 0) {
        output_text.append(QString("|%1").arg(context.line));
    }
    output_text.append(QString("] -- [ %1 ]").arg(msg));
    text_stream << output_text << Qt::endl;
}
void check_and_mkdir(){
    QString log_path = qApp->applicationDirPath();
    log_path.append("/log");
    QDir log_dir(log_path);
    if(!log_dir.exists()){
        qDebug() << log_path << " not exists";
        qDebug() << log_dir.mkdir(".");
    }else{
        qDebug() << log_path << " exists";
    }
}
void parse_commond_line(QApplication &app){
    QCommandLineParser parser;
    parser.setApplicationDescription("Example application");
    app.setApplicationVersion("version 0.1");
    //添加帮助选项
    QCommandLineOption helpOption = parser.addHelpOption();
    //添加版本选项
    QCommandLineOption versionOption = parser.addVersionOption();
    // 添加 --log 选项,这是一个没有值的开关选项
    QCommandLineOption logOption(QStringList() << "log",
        QCoreApplication::translate("main", "enable log functionality."));

    // 添加 --time 选项,这是一个没有值的开关选项
    QCommandLineOption timeOption(QStringList() << "time",
        QCoreApplication::translate("main", "enable show log time."));

    // 添加 --level 选项,这是一个带有值的选项
    QCommandLineOption levelOption(QStringList() << "level",
        QCoreApplication::translate("main", "set log level"),
        QCoreApplication::translate("main", "level"),  // 默认值(可选)
        "5");  // 值名称,用于解析 --level=VALUE

    QCommandLineOption debugOption(QStringList() << "debug",
        QCoreApplication::translate("main", "set log debug"),
        QCoreApplication::translate("main", "debug"),  // 默认值(可选)
        "2");  // 值名称,用于解析 --level=VALUE
    // 将选项添加到解析器
    parser.addOptions({ logOption, timeOption, levelOption, debugOption});

    // 解析命令行参数
    bool parseOk = parser.parse(QCoreApplication::arguments());
    qDebug() << "parseOk:" << parseOk;
    // 检查是否请求了帮助
    if (parser.isSet(helpOption)) {
        parser.showHelp();
        qDebug() << "-----------------------";
        qDebug() << parser.helpText(); // 输出帮助信息
        qDebug() << "-----------------------";
        exit(0);
    }
    // 检查是否请求了版本
    if (parser.isSet(versionOption)) {
        parser.showVersion(); // 输出帮助信息
        qDebug() << "after showVersion";
        app.processEvents();
        exit(0);
    }
    // 检查 --time 选项是否被设置
    bool timeEnabled = parser.isSet(timeOption);
    g_enable_debug_time = timeEnabled;
    // 检查 --log 选项是否被设置
    bool logEnabled = parser.isSet(logOption);
    qDebug() << "Log enabled:" << logEnabled;
    if(logEnabled){
        check_and_mkdir();
        // 检查 --level 选项的值
        bool hasLevel = parser.isSet(levelOption);
        if(hasLevel){
            QString levelQStringValue = parser.value(levelOption);
            bool isInt = false;
            int levelValue = levelQStringValue.toInt(&isInt,10);
            if(isInt){
                if(levelValue < 0){
                    levelValue = FORBID_LOG_OUTPUT_LEVEL;
                }
                log_level = levelValue;
            }else{
                log_level = FORBID_LOG_OUTPUT_LEVEL;
            }
        }else{
            log_level = FORBID_LOG_OUTPUT_LEVEL;
        }

        bool hasDebug = parser.isSet(debugOption);
        qDebug() << "hasDebug = " << hasDebug;
        if(hasDebug){
            QString debugQStringValue = parser.value(debugOption);
            bool isInt = false;
            int debugValue = debugQStringValue.toInt(&isInt,10);
            qDebug() << debugValue;
            if(isInt){
                if(debugValue < 0){
                    debugValue = NO_QDEBUG_LEVEL;
                }
                debug_log_level = (enum QtMsgType)debugValue;
            }else{
                debug_log_level = NO_QDEBUG_LEVEL;
            }
        }else{
            debug_log_level = NO_QDEBUG_LEVEL;
        }
        qInstallMessageHandler(myMessageOutput);
    }
}
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    parse_commond_line(app);
    int count = 0;
    while(count < 10000){
        count++;
        qDebug() << "count = " << count;
        qDebug() << "qDebug:hello log file";
        qInfo() << "qInfo:hello log file";
        qWarning() << "qWarning:hello log file";
        qCritical() << "QtCriticalMsg:hello log file";
    }
    qFatal("qFatal:hello log file");
    return app.exec();
}

测试结果:

运行后,会生成log文件夹,并生成文件console.log,内容如下:由执行结果可知函数会导致程序退出。

命令行参数 

#include <QApplication>
#include <QMutex>
#include <QMutexLocker>
#include <QFile>
#include <QDir>
#include <QDebug>
#include <QCommandLineParser>
#include <QDateTime>

static QMutex qml_logfile_mutex;
static int log_level = QtInfoMsg;
static bool g_enable_debug_time = false;
static enum QtMsgType debug_log_level = QtWarningMsg;
#define FORBID_LOG_OUTPUT_LEVEL (QtInfoMsg + 1)
#define NO_QDEBUG_LEVEL ((enum QtMsgType)(QtDebugMsg + 1))
void myMessageOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg) {
    static int file_index = 0;
    if(type < log_level){
        return;
    }
    if(type < debug_log_level){
        return;
    }
    QMutexLocker lock(&qml_logfile_mutex);

    QString filename = "";
    while (context.file != nullptr) {
        QStringList dirList;
        filename = context.file;
        if (filename.length() < 1) {
            break;
        }
        dirList = filename.split(QDir::separator());
        if (dirList.size() > 0) {
            filename = dirList[dirList.size() - 1];
        }
        if (filename.contains("/")) {
            dirList = filename.split("/");
            if (dirList.size() > 0) {
                filename = dirList[dirList.size() - 1];
            }
        }
        if (filename.contains("\\")) {
            dirList = filename.split("\\");
            if (dirList.size() > 0) {
                filename = dirList[dirList.size() - 1];
            }
        }
        break;
    };

    QString logFileFullName;
    logFileFullName = qApp->applicationDirPath();
    logFileFullName.append(QString("\\log\\console_%1.log").arg(file_index));
    QFile file(logFileFullName);
    do{
        if (!file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
            return;
        }
        if(file.pos() > 1024 * 1024){
            file.close();
            file_index++;
            QString new_file_name;
            new_file_name = qApp->applicationDirPath();
            new_file_name.append(QString("\\log\\console_%1.log").arg(file_index));
            file.setFileName(new_file_name);
            continue;
        }
        break;
    }while(1);

    QTextStream text_stream(&file);
    QString output_text;
    if(g_enable_debug_time){
        QString currentDateTime =
                QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss-zzz");
        output_text.append("[");
        output_text.append(currentDateTime);
        output_text.append("] ");
    }
    output_text.append("[");
    if (filename.length() > 0) {
        output_text.append(QString("%1").arg(type));
    }
    if (filename.length() > 0) {
        output_text.append(QString("|%1").arg(filename));
    }
    if (context.function != nullptr && strlen(context.function) > 0) {
        output_text.append(QString("|%1").arg(context.function));
    }

    if (context.line > 0) {
        output_text.append(QString("|%1").arg(context.line));
    }
    output_text.append(QString("] -- [ %1 ]").arg(msg));
    text_stream << output_text << Qt::endl;
}
void check_and_mkdir(){
    QString log_path = qApp->applicationDirPath();
    log_path.append("/log");
    QDir log_dir(log_path);
    if(!log_dir.exists()){
        qDebug() << log_path << " not exists";
        qDebug() << log_dir.mkdir(".");
    }else{
        qDebug() << log_path << " exists";
    }
}
void parse_commond_line(QApplication &app){
    QCommandLineParser parser;
    parser.setApplicationDescription("Example application");
    app.setApplicationVersion("version 0.1");
    //添加帮助选项
    QCommandLineOption helpOption = parser.addHelpOption();
    //添加版本选项
    QCommandLineOption versionOption = parser.addVersionOption();
    // 添加 --log 选项,这是一个没有值的开关选项
    QCommandLineOption logOption(QStringList() << "log",
        QCoreApplication::translate("main", "enable log functionality."));

    // 添加 --time 选项,这是一个没有值的开关选项
    QCommandLineOption timeOption(QStringList() << "time",
        QCoreApplication::translate("main", "enable show log time."));

    // 添加 --level 选项,这是一个带有值的选项
    QCommandLineOption levelOption(QStringList() << "level",
        QCoreApplication::translate("main", "set log level"),
        QCoreApplication::translate("main", "level"),  // 默认值(可选)
        "5");  // 值名称,用于解析 --level=VALUE

    QCommandLineOption debugOption(QStringList() << "debug",
        QCoreApplication::translate("main", "set log debug"),
        QCoreApplication::translate("main", "debug"),  // 默认值(可选)
        "2");  // 值名称,用于解析 --level=VALUE
    // 将选项添加到解析器
    parser.addOptions({ logOption, timeOption, levelOption, debugOption});

    // 解析命令行参数
    bool parseOk = parser.parse(QCoreApplication::arguments());
    qDebug() << "parseOk:" << parseOk;
    // 检查是否请求了帮助
    if (parser.isSet(helpOption)) {
        parser.showHelp();
        qDebug() << "-----------------------";
        qDebug() << parser.helpText(); // 输出帮助信息
        qDebug() << "-----------------------";
        exit(0);
    }
    // 检查是否请求了版本
    if (parser.isSet(versionOption)) {
        parser.showVersion(); // 输出帮助信息
        qDebug() << "after showVersion";
        app.processEvents();
        exit(0);
    }
    // 检查 --time 选项是否被设置
    bool timeEnabled = parser.isSet(timeOption);
    g_enable_debug_time = timeEnabled;
    // 检查 --log 选项是否被设置
    bool logEnabled = parser.isSet(logOption);
    qDebug() << "Log enabled:" << logEnabled;
    if(logEnabled){
        check_and_mkdir();
        // 检查 --level 选项的值
        bool hasLevel = parser.isSet(levelOption);
        if(hasLevel){
            QString levelQStringValue = parser.value(levelOption);
            bool isInt = false;
            int levelValue = levelQStringValue.toInt(&isInt,10);
            if(isInt){
                if(levelValue < 0){
                    levelValue = FORBID_LOG_OUTPUT_LEVEL;
                }
                log_level = levelValue;
            }else{
                log_level = FORBID_LOG_OUTPUT_LEVEL;
            }
        }else{
            log_level = FORBID_LOG_OUTPUT_LEVEL;
        }

        bool hasDebug = parser.isSet(debugOption);
        qDebug() << "hasDebug = " << hasDebug;
        if(hasDebug){
            QString debugQStringValue = parser.value(debugOption);
            bool isInt = false;
            int debugValue = debugQStringValue.toInt(&isInt,10);
            qDebug() << debugValue;
            if(isInt){
                if(debugValue < 0){
                    debugValue = NO_QDEBUG_LEVEL;
                }
                debug_log_level = (enum QtMsgType)debugValue;
            }else{
                debug_log_level = NO_QDEBUG_LEVEL;
            }
        }else{
            debug_log_level = NO_QDEBUG_LEVEL;
        }
        qInstallMessageHandler(myMessageOutput);
    }
}
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    parse_commond_line(app);
    int count = 0;
    while(count < 10000){
        count++;
        qDebug() << "count = " << count;
        qDebug() << "qDebug:hello log file";
        qInfo() << "qInfo:hello log file";
        qWarning() << "qWarning:hello log file";
        qCritical() << "QtCriticalMsg:hello log file";
    }
    qFatal("qFatal:hello log file");
    return app.exec();
}

测试

帮助信息测试:--help

输出的帮助信息

版本测试--version

 调试信息重定向测试--log --level=0

显示时间--log --level=0 --time

 小结

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网站灰度发布?Tomcat的8005、8009、8080三个端口的作用什么是CDNLVS、Nginx和Haproxy的优缺点服务器无法开机时

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c; 忍不住分享一下给大家。点击跳转到网站 学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把…

OpenGL ES 03 加载3张图片并做混合处理

OpenGL ES 02 加载3张图片并做混合处理 什么是纹理单元纹理单元的作用使用纹理单元的步骤详细解释加载图片并绑定到到GPU纹理单元采样器的设置1.设置采样器变量的纹理单元编号&#xff0c;目的是为了告诉纹理采样器&#xff0c;从哪个纹理单元采集数据2.如果你没有显式地设置采…

临床外显子组测序分析中的那些坑(上)

大规模并行测序技术或下一代测序已成为基因诊断和研究的标准技术&#xff0c;尤其是外显子组和基因组测序现在已经在世界范围内广泛应用于患者的分子诊断。在过去几年中&#xff0c;许多实验室都在努力应对基于全新技术建立基因检测工作流程的挑战。测序技术中持续引入新的仪器…

【Tomcat】第六站(最后一站啦!):数据的返回

1. 引言 前端资源比如html页面&#xff0c;进行返回。截止到目前我们写的项目架构不支持前端页面&#xff08;静态资源 &#xff09;。 2. 数据的返回 2.1 准备 为了能够写前端页面&#xff0c;新建一个项目。选择Maven项目&#xff0c;下一步&#xff0c;下一步。 加载完…

ai论文生成器:分享8款AI一键生成论文的写作软件

在撰写毕业论文的过程中&#xff0c;高效利用各类软件工具可以极大地提升写作效率与质量。以下是八个免费的神器软件工具&#xff0c;它们各自在论文撰写、文献管理、语法校对、数据可视化等方面发挥着重要作用。希望这些推荐能帮助你顺利完成毕业论文的写作。 千笔AI论文&…

【Ubuntu 20.04】notepad++的安装与汉化

一&#xff0c;简介 本文介绍如何在Ubuntu虚拟机中安装notepad&#xff0c;供参考。 二&#xff0c;操作步骤 2.1 notepad的安装 sudo snap install notepad-plus-plus

Cherno C++学习笔记 P45 拷贝与拷贝构造函数

在这一篇文章当中&#xff0c;我们会学习一下C当中的复制以及复制构造函数&#xff0c;当然&#xff0c;还会用一个相对比较完整的代码类作为例子。这也是我们第一次写一个相对比较长的和完整的代码。 对于C来说&#xff0c;理解复制是非常重要的&#xff0c;因为整个C变成可以…

uniapp入门 01创建项目模版

0安装 hbuilder x 标准版 1.创建模版工程 2.创建官方 案例工程 index.uvuewen 文件解析 <!-- 模版 标签 --> <template><view></view></template><!-- 脚本 --> <script>export default {data() {return {}},onLoad() {},methods:…

kubeadm安装K8s高可用集群之集群初始化及master/node节点加入calico网络插件安装

系列文章目录 1.kubeadm安装K8s高可用集群之基础环境配置 2.kubeadm安装K8s集群之高可用组件keepalivednginx及kubeadm部署 3.kubeadm安装K8s高可用集群之集群初始化及master/node节点加入集群calico网络插件安装 kubeadm安装K8s高可用集群之集群初始化及master/node节点加入ca…

【NLP】序列到序列(seq2seq)建模工具fairseq使用详解

文章目录 一、fairseq简介二、安装方式2.1 pip安装2.2 源码安装 三、fairseq命令工具3.1 fairseq-preprocess3.2 fairseq-train3.3 fairseq-generate3.4 fairseq-interactivate3.5 fairseq-score3.6 fairseq-eval-lm 4. 常见报错报错1 参考资料 一、fairseq简介 fairseq 是 Fa…

28、论文阅读:基于像素分布重映射和多先验Retinex变分模型的水下图像增强

A Pixel Distribution Remapping and Multi-Prior Retinex Variational Model for Underwater Image Enhancement 摘要介绍相关工作基于模型的水下图像增强方法&#xff1a;无模型水下图像增强方法&#xff1a;基于深度学习的水下图像增强方法&#xff1a; 论文方法概述像素分布…

ArkTs组件的学习

一. AlphabetIndexer 可以与容器组件联动用于按逻辑结构快速定位容器显示区域的组件 参数名类型必填说明arrayValueArray<string>是字母索引字符串数组&#xff0c;不可设置为空selectednumber是初始选中项索引值若超出索引值范围则取默认值0 class Lxr{tImg:Resource…

Python读取Excel批量写入到PPT生成词卡

一、问题的提出 有网友想把Excel表中的三列数据&#xff0c;分别是&#xff1a;单词、音标和释义分别写入到PPT当中&#xff0c;每一张PPT写一个单词的内容。这种批量操作是python的强项&#xff0c;尤其是在办公领域&#xff0c;它能较好地解放双手&#xff0c;读取Excel表后…

百度面试手撕 go context channel部分学习

题目 手撕 对无序的切片查询指定数 使用context进行子协程的销毁 并且进行超时处理。 全局变量定义 var (startLoc int64(0) // --- 未处理切片数据起始位置endLoc int64(0) // --- 切片数据右边界 避免越界offset int64(0) // --- 根据切片和协程数量 在主线程 动态设…

Otsu 二值化算法:原理、实现与应用

摘要&#xff1a; 本文深入探讨了 Otsu 二值化算法&#xff0c;详细阐述其原理&#xff0c;包括类间方差的计算与阈值确定机制。分别给出了该算法在 C#、Python 和 C 中的实现代码示例&#xff0c;并对代码进行了详细注释与分析。此外&#xff0c;还探讨了 Otsu 二值化算法在图…

uniApp使用腾讯地图提示未添加maps模块

uniApp使用腾讯地图&#xff0c;打包提示未添加maps模块解决方案 这是报错信息&#xff0c;在标准基座运行的时候是没问题的&#xff0c;但是打包后会提示未添加&#xff0c;可以通过在mainfest里面把地图插件上腾讯地图的key更换高德地图的key&#xff0c;定位服务可以继续用腾…

Deepin/Linux clash TUN模式不起作用,因网关导致的问题的解决方案。

网关导致的问题的解决方案 查看路由 ip route寻找默认路由 默认路由应当为Mihomo default dev Mihomo scope link 如果不是&#xff0c;则 sudo ip route add default dev Mihomo在clash TUN开关状态发生变化时&#xff0c;Mihomo网卡会消失&#xff0c;所以提示找不到网卡…

scala中正则表达式的使用

正则表达式&#xff1a; 基本概念 在 Scala 中&#xff0c;正则表达式是用于处理文本模式匹配的强大工具。它通过java.util.regex.Pattern和java.util.regex.Matcher这两个 Java 类来实现&#xff08;因为 Scala 运行在 Java 虚拟机上&#xff0c;可以无缝使用 Java 类库&…

apache应用(客户机地址限制、用户授权限制、日志分割、AWStats日志分析)

目录 一、 客户机地址限制 二、 用户授权限制 三、 日志分割 使用rotatelogs分割工具 使用第三方工具cronolog 四、 AWStats日志分析 具体的apache软件安装可以阅读我之前的文章apache安装https://blog.csdn.net/m0_68472908/article/details/139348739?spm1001.2014.300…

护士资格实践题库(含解析)

1.患者女&#xff0c;30岁。诊断类风湿关节炎入院&#xff0c;经使用药物治疗后患者关节疼痛减轻&#xff0c;但出现体重增加、满月脸、向心性肥胖。提示存在何种药物的副作用&#xff08; &#xff09; A.泼尼松 B.环磷酰胺 C.硫唑嘌呤 D.吲哚美辛 E.阿司匹林 【答案】…