QT 重定向qdebug输出到自绘界面

因为在嵌入式中调试qt需要查看输出信息,特意写了一个类用户便捷查看qdebug信息

界面如下:

提供了开始,停止,保存,清空,退出功能,具体代码下文给出

文件如下

#ifndef QDEBUGREDIRECT_H
#define QDEBUGREDIRECT_H
/*
 *qdebug  重定向类 定向到界面控件
 *李吉磊 2023.12.7
 *
*/

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>
#include <QTextEdit>
#include <QWidget>
#include <QMutex>


class qDebugRedirect : public QObject
{
    Q_OBJECT
public:
    qDebugRedirect();
    void showWidget();    //展示界面
    void closeWidget();    //关闭界面
    static void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg);

private:
    void InitWidget();
    void StartRedirect();     //启动注册
    void StopRedirect();      //停止注册
    void Save2File();         //将界面文本内容保存到本地
    QWidget * m_widget;  //界面
    QTextEdit * m_Edit;
    QMutex m_mutex;
};

#endif // QDEBUGREDIRECT_H
#include "qdebugredirect.h"
#include <QGridLayout>
#include <QDebug>
#include <QDateTime>
#include <QDir>
qDebugRedirect * g_qDebugRedirect;

qDebugRedirect::qDebugRedirect()
{
    m_widget = nullptr;
    g_qDebugRedirect = this;
    //下面两行为在构造该类时启动重定向,后续只要展示出界面即可查看信息
    InitWidget();
    StartRedirect();
}

void qDebugRedirect::myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    // 加锁
    g_qDebugRedirect->m_mutex.lock();

    //信息分类
    QString strMsg("");
    QByteArray localMsg = msg.toLocal8Bit();
    switch(type)
    {
    case QtDebugMsg:
        strMsg = QString("Debug:");
        break;
    case QtInfoMsg:
        strMsg = QString("Info:");
        break;
    case QtWarningMsg:
        strMsg = QString("Warning:");
        break;
    case QtCriticalMsg:
        strMsg = QString("Critical:");
        break;
    case QtFatalMsg:
        strMsg = QString("Fatal:");
        break;
    default:
        break;
    }

    //文件名、函数名、行数
    strMsg += QString("Function: %1  File: %2  Line: %3 ").arg(context.function).arg(context.file).arg(context.line);

    // 时间和内容
    QString strDateTime = QDateTime::currentDateTime().toString("hh:mm:ss");
    QString strMessage = QString("%1 %2:%3").arg(strDateTime).arg(strMsg).arg(localMsg.constData());
    int maxLen = 2*1024*1024;
    int len = g_qDebugRedirect->m_Edit->toPlainText().length();
    if(len > maxLen)
        g_qDebugRedirect->m_Edit->clear();
    g_qDebugRedirect->m_Edit->append(strMessage);
    g_qDebugRedirect->m_Edit->moveCursor(QTextCursor::End);

    // 解锁
    g_qDebugRedirect->m_mutex.unlock();

}


void qDebugRedirect::StartRedirect()
{
    qInstallMessageHandler(myMessageOutput);
}

void qDebugRedirect::StopRedirect()
{
    qInstallMessageHandler(nullptr);
}

void qDebugRedirect::InitWidget()
{
    if(m_widget == nullptr)
    {
        m_widget = new QWidget();
        QGridLayout * glay = new QGridLayout();
        glay->setSpacing(0);
        glay->setMargin(0);
        glay->setContentsMargins(0,0,0,0);
        m_widget->setLayout(glay);
        QPushButton * pbClose = new QPushButton();  //关闭界面按钮
        pbClose->setText("close");
        QObject::connect(pbClose,&QPushButton::clicked,this,[=](){
            closeWidget();
            //qDebug() << "close";
        });
        glay->addWidget(pbClose,0,8,1,1);
        QPushButton * pbBegin = new QPushButton();  //开始按钮
        pbBegin->setText("start");
        QObject::connect(pbBegin,&QPushButton::clicked,this,[=](){StartRedirect();});
        glay->addWidget(pbBegin,1,0,1,2);
        QPushButton * pbEnd = new QPushButton();    //结束按钮
        pbEnd->setText("stop");
        QObject::connect(pbEnd,&QPushButton::clicked,this,[=](){StopRedirect();});
        glay->addWidget(pbEnd,1,2,1,2);
        QPushButton * pSave = new QPushButton();    //保存按钮
        pSave->setText("save");
        QObject::connect(pSave,&QPushButton::clicked,this,[=](){Save2File();});
        glay->addWidget(pSave,1,4,1,2);
        QPushButton * pClear = new QPushButton();    //清理按钮
        pClear->setText("clear");
        QObject::connect(pClear,&QPushButton::clicked,this,[=](){
            m_Edit->clear();
        });
        glay->addWidget(pClear,1,8,1,1);


        //展示控件
        m_Edit = new QTextEdit();
        glay->addWidget(m_Edit,2,0,6,9);
        //m_widget->setWindowFlag(Qt::WindowStaysOnTopHint,true);
        //m_widget->setWindowFlags(Qt::FramelessWindowHint);
        //m_widget->setWindowModality(Qt::ApplicationModal);
        m_widget->resize(800,600);
    }
}

void qDebugRedirect::showWidget()    //展示界面
{
    InitWidget();
    m_widget->show();
}

void qDebugRedirect::closeWidget()    //关闭界面
{
    if(m_widget)
    {
        m_widget->close();
        delete m_widget;
        m_widget = nullptr;
    }
}

void qDebugRedirect::Save2File()
{
    //创建log文件夹
    qDebug() << "currentPath : " << QDir::currentPath();

    QDir dir("log");
    if (!dir.exists())
    {
        QDir dir;
        bool b = dir.mkdir("log");
        qDebug() << "dir.mkdir(\"log\") = "  << b;
    }

    //创建log文件
    QString currentDate = QDateTime::currentDateTime().toString("yyyyMMdd");
    QString logName = "log" + currentDate + ".txt";
    QString logFileName = "log/" + logName;

    //写入文件
    QFile file(logFileName);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Append))
    {
        qDebug() << "file.open : " << logFileName << "faild";
        file.close();
        return ;
    }
    qDebug() << "file.open : " << logFileName << "succeed";
    QTextStream stream(&file);
    stream << m_Edit->toPlainText() << "\r\n";;
    file.flush();
    file.close();
}



使用方法也很简单

先构造

qDebugRedirect * m_widget;

m_widget = new qDebugRedirect();

然后展示界面或关闭界面

m_widget->showWidget();   展示界面

m_widget->closeWidget();  关闭界面

当然了界面自带close 按钮 或者 窗体的x 退出按钮均可退出

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

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

相关文章

【dig命令查询方法】

dig&#xff08;Domain Information Groper&#xff09;是一个用于查询DNS&#xff08;域名系统&#xff09;的命令行工具&#xff0c;它可以帮助您获取关于域名的各种信息&#xff0c;如IP地址、MX记录、NS记录等。下面是dig的详细使用教程。 基本语法&#xff1a; dig [ser…

【数据库】树形数据组织架构下的封锁并发控制,B树索引并发访问控制,树协议原理及案例分析

数据库并发访问树协议 ​专栏内容&#xff1a; 手写数据库toadb 本专栏主要介绍如何从零开发&#xff0c;开发的步骤&#xff0c;以及开发过程中的涉及的原理&#xff0c;遇到的问题等&#xff0c;让大家能跟上并且可以一起开发&#xff0c;让每个需要的人成为参与者。 本专栏会…

docker基本管理和概念

1、定义&#xff1a;一个开源的应用容器引擎&#xff0c;基于go语言开发&#xff0c;运行在liunx系统中的开源的、轻量级的“虚拟机” docker的容器技术可以在一台主机上轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器 docker的宿主机是liunx系统&#xff0c;集…

深度学习与逻辑回归模型的融合--TensorFlow多元分类的高级应用

手写数字识别 文章目录 手写数字识别1、线性回归VS逻辑回归Sigmoid函数 2、逻辑回归的基本模型-神经网络模型3、多元分类基本模型4、TensorFlow实战解决手写数字识别问题准备数据集数据集划分 特征数据归一化归一化方法归一化场景 标签数据独热编码One-Hot编码构建模型损失函数…

NLP自然语言处理学习笔记

参考&#xff1a;NLP&#xff08;自然语言处理&#xff09;介绍 - 知乎 (zhihu.com) 一、NLP是什么 自然语言处理( Natural Language Processing, NLP)是计算机科学领域与人工智能领域中的一个重要方向。它研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法。自…

uni-app 微信小程序之好看的ui登录页面(一)

文章目录 1. 页面效果2. 页面样式代码 更多登录ui页面 uni-app 微信小程序之好看的ui登录页面&#xff08;一&#xff09; uni-app 微信小程序之好看的ui登录页面&#xff08;二&#xff09; uni-app 微信小程序之好看的ui登录页面&#xff08;三&#xff09; uni-app 微信小程…

原生微信小程序将字符串生成二维码图片

weapp-qrcode.js再最后 inde.ts中的内容 // pages/qrCode/index.ts // 引入weapp-qrcode.js文件 var QRCode require(../../utils/weapp-qrcode) Page({/*** 页面的初始数据*/data: {orderNo:"",imagePath:},/*** 生命周期函数--监听页面加载*/onLoad(options:any)…

渗透测试(Lab1.0)

1、用搜索引擎Google或百度搜索麻省理工学院网站中文件名包含“network security”的pdf文档&#xff0c;截图搜索得到的页面。 2、照片中的女生在哪里旅行&#xff1f; 截图搜索到的地址信息。 搜索餐厅的名字&#xff0c;找一下关键词 3、手机位置定位 通过LAC&#xff0…

【AIGC】prompt工程从入门到精通--图片生成专题

本文为系列教程【AIGC】prompt工程从入门到精通的子教程。 一、介绍 与文本提示相比&#xff0c;找到最佳的提示词来生成完美的图片并没有那么成熟。这可能是因为创建对象自身的挑战&#xff0c;这些对象基本上是主观的并且往往缺乏良好的准确性度量方法。 本指南涵盖了基本…

前端典例算法集合

前言 刷算法顺序&#xff1a;1、熟悉本文章第1点的内容&#xff1b;2、刷力扣算法&#xff0c;可以参考这本书的顺序与思想&#xff1a;代码随想录完整版PDF下载 | 合集下载 | 百度云 | | 代码随想录 (programmercarl.com) 3、刷牛客的高频考题 1、熟悉数组Array&#xff0c…

uni-app 微信小程序之好看的ui登录页面(四)

文章目录 1. 页面效果2. 页面样式代码 更多登录ui页面 uni-app 微信小程序之好看的ui登录页面&#xff08;一&#xff09; uni-app 微信小程序之好看的ui登录页面&#xff08;二&#xff09; uni-app 微信小程序之好看的ui登录页面&#xff08;三&#xff09; uni-app 微信小程…

uni-app 微信小程序之好看的ui登录页面(二)

文章目录 1. 页面效果2. 页面样式代码 更多登录ui页面 uni-app 微信小程序之好看的ui登录页面&#xff08;一&#xff09; uni-app 微信小程序之好看的ui登录页面&#xff08;二&#xff09; uni-app 微信小程序之好看的ui登录页面&#xff08;三&#xff09; uni-app 微信小程…

2023五岳杯量子计算挑战赛数学建模思路+代码+模型+论文

目录 计算力网络&#xff08;CPN&#xff09;是一种新型的信息基础设施&#xff0c;完整论文代码见文末 问题描述 2.1 问题1 2.2 问题2 2.3 问题3 问题1的解答过程&#xff1a; 问题3的解答过程&#xff1a; 决策优化应用场景&#xff1a;人工智能模型超参数调优 背景信…

【开源】基于Vue和SpringBoot的车险自助理赔系统

项目编号&#xff1a; S 018 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S018&#xff0c;文末获取源码。} 项目编号&#xff1a;S018&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 角色管理模块2.3 车…

MQTT源码分析

目录 MQTT源码分析 1. MQTT客户端功能 2. 客户端软件如何实现 3. 程序分层 4. 情景分析 4.1 连接服务器 4.2 创建线程 4.3 发布消息 4.4 最复杂&#xff1a;订阅消息 MQTT源码分析 分析源码&#xff1a;mqttclient\test\emqx\test.c 参考资料&#xff1a; kawaii-mqt…

【开源】基于Vue.js的二手车交易系统

文末获取源码&#xff0c;项目编号&#xff1a; S 084 。 \color{red}{文末获取源码&#xff0c;项目编号&#xff1a;S084。} 文末获取源码&#xff0c;项目编号&#xff1a;S084。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 二手车档案管理模块…

RabbitMQ 常见面试题

目录 1.前置知识1.1.什么是 MQ&#xff1f;它有什么作用&#xff1f;1.2.什么是消费者生产者模型&#xff1f;1.3.AMQP 是什么&#xff1f; 2.RabbitMQ 入门2.1.什么是 RabbitMQ&#xff1f;有什么特点&#xff1f;2.2.RabbitMQ 的核心概念有哪些&#xff1f;2.2.1.生产者 (Pro…

720度vr虚拟家居展厅提升客户的参观兴致

VR虚拟展厅线上3D交互展示的优势有以下几点&#xff1a; 打破了场馆的展示限制&#xff0c;可展示危险性制品、珍贵稀有物品、超大型设备等&#xff0c;同时提供了更大的展示空间和更丰富的展示内容。 可提供企业真实环境的实时VR全景参观&#xff0c;提升潜在客户信任度。 提供…

go的两大测试方法- 官网推荐

go的两大测试方法- 官网推荐 go的两大测试方法- 官网推荐常见的不正规测试方法main方法个例测试验证 - 不正规1. 提供一个函数&#xff1a;Reverse(input string)进行测试2. 直接在函数下创建main函数下进行个例测试3. 测试发现&#xff0c;Reverse方法不支持某些汉字&#xff…

AZURE==SQL managed instances

创建资源 创建DB 创建完成后&#xff0c;拿着刚才的账号密码依然连接不上 远程连接 需要开启公网访问和开放相关端口 参考Configure public endpoint - Azure SQL Managed Instance | Microsoft Learn 连接成功