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

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=VALUEQCommandLineOption 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=VALUEQCommandLineOption 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.mzph.cn/news/890101.shtml

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

相关文章

面试小札:Java后端闪电五连鞭_8

1. Kafka消息模型及其组成部分 - 消息&#xff08;Message&#xff09;&#xff1a;是Kafka中最基本的数据单元。消息包含一个键&#xff08;key&#xff09;、一个值&#xff08;value&#xff09;和一个时间戳&#xff08;timestamp&#xff09;。键可以用于对消息进行分区等…

穷举vs暴搜vs深搜vs回溯vs剪枝专题一>全排列II

题目&#xff1a; 解析&#xff1a; 这题设计递归函数&#xff0c;主要把看如何剪枝 代码&#xff1a; class Solution {private List<List<Integer>> ret;private List<Integer> path;private boolean[] check;public List<List<Integer>> p…

Python如何正确解决reCaptcha验证码(9)

前言 本文是该专栏的第73篇,后面会持续分享python爬虫干货知识,记得关注。 我们在处理某些国内外平台项目的时候,相信很多同学或多或少都见过,如下图所示的reCaptcha验证码。 而本文,笔者将重点来介绍在实战项目中,遇到上述中的“reCaptcha验证码”,如何正确去处理并解…

【Python函数】对 LEGB 规则以及 nonlocal 和 global 语法的掌握

def outter():def innerA():x 100def innerB():nonlocal xx 250def innerC():global xx 520x 880innerA()print(f"调用完 innerA() 函数之后&#xff0c;x {x}")innerB()print(f"调用完 innerB() 函数之后&#xff0c;x {x}")innerC()print(f"调…

java_零钱通项目

SmallChangeSysOOP.java package com.hspedu.smallchange.oop;import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner;/*** 该类是完成零钱通的各个功能的类* 使用OOP(面向对象编程&#xff09;*/ public class SmallChangeSysOOP {// 定义相关…

Mamba安装环境和使用,anaconda环境打包

什么是mamba Mamba是一个极速版本的conda&#xff0c;它是conda的C重新实现&#xff0c;使用多线程并行处理来加速包和依赖项的下载。 Mamba旨在提高安装、更新和卸载Python包的速度&#xff0c;同时保持与conda相同的兼容性和命令行接口。 Mamba的核心部分使用C实现&#xff…

网络多层的协议详述

网络层 1&#xff09;地址管理&#xff1a;制定一系列的规则&#xff0c;通过地址&#xff0c;在网络上描述出一个设备的位置 2&#xff09;路由选择&#xff1a;网络环境比较复杂&#xff0c;从一个节点到另一个节点&#xff0c;存在很多条不同的路径&#xff0c;需要规划出…

【异常】GL-SFT1200路由器中继模式,TL-CPE1300D无法搜寻5G网问题分析

【异常】GL-SFT1200路由器中继模式,TL-CPE1300D无法搜寻5G网问题 情况实验结论情况 在用GL-SFT1200路由器切换中继模式时,由于web密码忘却,需要重置,但根据官网使用手册,或者对应的中文版手册,重置失败。通过跟商家联系,进行uboot刷机,提供了指导文档,尝试后刷机成功…

《算法ZUC》题目

判断题 ZUC算法LFSR部分产生的二元序列具有很低的线性复杂度。 A.正确 B.错误 正确答案A 单项选择题 ZUC算法驱动部分LFSR的抽头位置不包括&#xff08; &#xff09;。 A.s15 B.s10 C.s7 D.s0 正确答案C 单项选择题 ZUC算法比特重组BR层主要使用了软件实现友好的…

交换机vlan划分以及端口隔离

vlan 1、基于接口划分vlan 2、基于mac地址划分vlan (接口最好设置为hybird&#xff0c;如果是access和trunk的话&#xff0c;当mac地址匹配到的vlan跟接口的pvid不一致时&#xff0c;不允许通过&#xff1b;而hybird口可以很好的支持多个vlan去除tag后直连设备) #在vlan视…

Flink SQL 从一个SOURCE 写入多个Sink端实例

一. 背景 FLINK 任务从一个数据源读取数据, 写入多个sink端. 二. 官方实例 写入多个Sink语句时&#xff0c;需要以BEGIN STATEMENT SET;开头&#xff0c;以END;结尾。--源表 CREATE TEMPORARY TABLE datagen_source (name VARCHAR,score BIGINT ) WITH (connector datagen …

.vscode配置文件备份

vscode插件 位于&#xff1a;C:\Users\用户名\AppData\Roaming\Code\User\settings.json settings.json {// "C_Cpp.intelliSenseEngine": "default",//智能查找默认值"C_Cpp.intelliSenseEngineFallback": "enabled", //需要添加的…

(Image Signal Processor)ISP简介

文章目录 ISP功能简介ISP的主要功能ISP的主要模块1. **黑电平校正&#xff08;Black Level Correction, BLC&#xff09;**2. **噪声去除&#xff08;Denoise&#xff09;**3. **色彩校正&#xff08;Color Correction Matrix, CCM&#xff09;**4. **自动曝光&#xff08;Auto…

代码随想录day23 | leetcode 39.组合总和 40.组合总和II

39.组合总和 Java class Solution { List<List<Integer>> result new ArrayList<>();LinkedList<Integer> path new LinkedList<>();public List<List<Integer>> combinationSum(int[] candidates, int target) {Arrays.sor…

将HTML转换为PDF:使用Spire.Doc的详细指南

目录 引言 1. 为什么选择 Spire.Doc&#xff1f; 1.1 主要特点 1.2 适用场景 2. 准备工作 2.1 引入 Spire.Doc 依赖 2.2 禁用 SSL 证书验证 3. 实现功能 3.1 主类结构 3.2 代码解析 4. 处理图像 5. 性能优化 5.1 异步下载图像 示例代码 5.2 批量处理优化 示例代…

jmeter监控服务器性能信息

概述 Apache JMeter 是一个功能强大的开源工具,主要用于进行压力测试和性能测试。除了用于模拟用户行为进行压力测试外,JMeter 还提供了一些功能来监控服务器性能。 性能测试时我们关注的重要指标是:并发用户数,TPS,请求成功率,响应时间,服务器的CPU,memory, l/0 dis…

关于Buildroot如何配置qtwebengine [未能成功编译]

目录 前言 下载Buildroot 如何添加qtwebengine 开始make编译 编译过程中到了这些问题 前言 问题的开始就在于学习QT的过程中遇到了一个问题… Unknown module(s) in QT: webenginewidgets 我想要把qt的一个项目编译并发送到我的开发板上&#xff0c;但是qmake识别不到这…

SNP与Scheer合作助力Warsteiner Brauerei成功升级至SAP S/4HANA

德国软件和咨询公司SNP是SAP环境中数字化转型、自动化数据迁移和数据管理软件的知名提供商&#xff0c;再次与德国Scheer公司合作&#xff0c;Scheer公司是一家专门从事业务流程管理和SAP咨询的咨询公司。他们为家族企业Warsteiner Brauerei Haus Cramer KG向SAP S/4HANA升级转…

Apache Samza开源的分布式流处理框架

Apache Samza 是一个开源的分布式流处理框架,用于处理实时数据流和分布式任务。它最初由 LinkedIn 开发,并在 2014 年捐赠给 Apache 软件基金会。Samza 的设计目标是为开发人员提供一个易用、可靠、高效的流处理工具。以下是其关键特点和架构的简介: 核心特点 简单的编程模…

【Super Tilemap Editor使用详解】(五):图块调色板

1、图块调色板&#xff08;Tile Palette&#xff09;可以在以下位置找到&#xff1a; Tileset Inspector检视面板 STETilemap Inspector检视面板&#xff0c;并选择 "Paint" 选项卡 Tile Palette 窗口&#xff1a;"SuperTilemapEditor/Window/Tile Palette Win…