C++学习之路(九)C++ 用Qt5实现一个工具箱(增加一个JSON数据格式化功能)- 示例代码拆分讲解

上篇文章,我们用 Qt5 实现了在小工具箱中添加了《粘贴板记录管理》功能,用着还不错哈。为了继续丰富我们的工具箱,今天我们就再增加一个平时经常用到的功能吧,就是「 JSON数据格式化 」功能。下面我们就来看看如何来规划开发一个这样的小功能并且添加到我们的工具箱中吧。

老规矩,先看效果

在这里插入图片描述

功能规划

这个JSON格式化功能是工具箱的一部分,它允许用户输入JSON数据并对其进行格式化排版。主要功能包括:

  1. JSON数据格式化: 用户可以在文本框中输入或粘贴JSON格式的数据。
  2. 格式化按钮: 点击“格式化JSON”按钮后,程序会尝试解析用户输入的JSON数据。如果数据有效,它会重新排列和缩进JSON数据,使其结构更清晰、易读。
  3. 错误处理: 如果JSON数据无效(格式错误),程序会弹出警告消息框提示用户错误的具体信息,让用户知晓数据存在问题。
    在这里插入图片描述

这个功能对于需要处理JSON数据的开发者或用户来说非常实用,它能够帮助他们快速查看和理解JSON数据的结构和内容,减少了手动排版的工作,提高了效率。

看完介绍就直接上代码

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QMessageBox>
#include <QDebug>
#include <QListWidget>
#include <QClipboard>
#include <QMimeData>
#include <QTextEdit>
#include <QJsonDocument>
#include <QJsonObject>

#define myApp (dynamic_cast<QApplication *>(QCoreApplication::instance()))

class JsonFormatter : public QWidget {
Q_OBJECT
public:
    explicit JsonFormatter(QWidget *parent = nullptr) : QWidget(parent) {
        auto *layout = new QVBoxLayout(this);

        inputTextEdit = new QTextEdit(this);
        layout->addWidget(inputTextEdit);

        formatButton = new QPushButton("格式化", this);
        connect(formatButton, &QPushButton::clicked, this, &JsonFormatter::formatJson);
        layout->addWidget(formatButton);

        outputTextEdit = new QTextEdit(this);
        outputTextEdit->setReadOnly(true);
        layout->addWidget(outputTextEdit);

        setLayout(layout);
    }

private slots:
    void formatJson() {
        QString inputText = inputTextEdit->toPlainText();
        QJsonParseError error{};
        QJsonDocument jsonDoc = QJsonDocument::fromJson(inputText.toUtf8(), &error);

        if (error.error != QJsonParseError::NoError) {
            outputTextEdit->setText("JSON 解析错误:" + error.errorString());
            return;
        }

        QJsonObject jsonObj = jsonDoc.object();
        QJsonDocument formattedJson(jsonObj);

        outputTextEdit->setText(formattedJson.toJson());
    }

private:
    QTextEdit *inputTextEdit;
    QPushButton *formatButton;
    QTextEdit *outputTextEdit;
};

class ClipboardManager : public QWidget {
Q_OBJECT
public:
    explicit ClipboardManager(QWidget *parent = nullptr) : QWidget(parent) {
        auto *layout = new QVBoxLayout(this);

        listWidget = new QListWidget(this);
        updateList(); // 初始更新列表

        auto *clearButton = new QPushButton("清空记录", this);
        connect(clearButton, &QPushButton::clicked, this, &ClipboardManager::clearClipboard);

        layout->addWidget(listWidget);
        layout->addWidget(clearButton);

        setLayout(layout);

        connect(myApp->clipboard(), &QClipboard::dataChanged, this, &ClipboardManager::updateList);
    }

private slots:
    void updateList() {
        const QClipboard *clipboard = myApp->clipboard();
        const QMimeData *mimeData = clipboard->mimeData();

        if (mimeData->hasText()) {
            const QString clipboardText = mimeData->text();

            if (!clipboardText.isEmpty()) {
                listWidget->addItem(clipboardText);
            }
        }
    }

    void clearClipboard() {
        myApp->clipboard()->clear();
        listWidget->clear();
    }

private:
    QListWidget *listWidget;
};

class MyMainWindow : public QWidget {
Q_OBJECT
public:
    explicit MyMainWindow(QWidget *parent = nullptr) : QWidget(parent) {
        setWindowTitle("天河工具箱");

        auto *layout = new QVBoxLayout(this);

        auto *clipboardButton = new QPushButton("管理粘贴板记录");
        connect(clipboardButton, &QPushButton::clicked, this, &MyMainWindow::toggleClipboardManager);
        clipboardManager = new ClipboardManager(this);
        clipboardManager->hide();
        layout->addWidget(clipboardManager);
        layout->addWidget(clipboardButton);

        auto *jsonFormatButton = new QPushButton("格式化 JSON");
        connect(jsonFormatButton, &QPushButton::clicked, this, &MyMainWindow::toggleJsonFormatter);
        jsonFormatter = new JsonFormatter(this);
        jsonFormatter->hide();
        layout->addWidget(jsonFormatter);
        layout->addWidget(jsonFormatButton);

        setLayout(layout);
    }

private slots:

    void toggleClipboardManager() {
        if (clipboardManager->isHidden()) {
            clipboardManager->show();
        } else {
            clipboardManager->hide();
        }
    }

    void toggleJsonFormatter() {
        if (jsonFormatter->isHidden()) {
            jsonFormatter->show();
        } else {
            jsonFormatter->hide();
        }
    }

private:
    ClipboardManager *clipboardManager;
    JsonFormatter *jsonFormatter;
};

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);

    MyMainWindow mainWindow;
    mainWindow.show();

    return QApplication::exec();
}

#include "main.moc"

看完代码了吗?

看完了我们就开始拆分讲解一下JSON数据格式化的功能吧,还有我们用到的相关知识点,最后我们再来一些注意事项就算完成任务了~

先从整体来拆解,看一下我们的代码。代码包含了两个自定义的小部件类:JsonFormatterClipboardManager。它们被整合到了 MyMainWindow 中,提供了管理粘贴板记录和JSON格式化的功能。

JsonFormatter 类

这个类用于实现 JSON 格式化的功能。它包含了两个文本框和一个按钮,按钮用于触发格式化操作。主要功能有:

  • 构造函数: 创建了界面所需的部件,并设置了布局。
  • formatJson 函数(槽函数): 当格式化按钮被点击时,该函数将尝试解析输入文本框中的 JSON 数据。如果解析成功,它会对 JSON 数据进行格式化,并将格式化后的结果显示在输出文本框中。

ClipboardManager 类

这个类用于管理粘贴板记录。它包含了一个列表部件和一个按钮,按钮用于清空记录。主要功能有:

  • 构造函数: 创建了界面所需的部件,并设置了布局。
  • updateList 函数(槽函数): 当剪贴板的数据发生变化时,该函数会更新粘贴板记录列表。它会获取剪贴板中的文本数据,并将非空文本添加到记录列表中。
  • clearClipboard 函数(槽函数): 当清空记录按钮被点击时,该函数会清空粘贴板的内容,并清空记录列表。

MyMainWindow 类

这个类是主窗口类,整合了 ClipboardManagerJsonFormatter 类的功能,并提供了按钮用于切换这两个功能的显示和隐藏。

主函数

在主函数中,创建了 QApplication 对象,并实例化了 MyMainWindow 类作为应用的主窗口,最后通过 QApplication::exec() 运行应用。

这些类结合了 Qt 的布局管理器和信号槽机制,提供了简单而有效的用户界面,并为用户提供了管理粘贴板和JSON格式化的功能。


下面就着重讲解今天的主角 JsonFormatter 类

让我们来仔细看一下 JsonFormatter 类的代码,并分段进行介绍讲解。

头文件
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QTextEdit>
#include <QJsonDocument>
#include <QJsonObject>

JsonFormatter 类用到了 QWidgetQPushButtonQVBoxLayoutQTextEditQJsonDocumentQJsonObject 等 Qt 的头文件,用于界面构建和 JSON 数据处理。

  • QWidget:Qt 中用于构建用户界面的基类。JsonFormatter 类继承自 QWidget,用于创建 JSON 格式化功能的界面部件。

  • QPushButton:Qt 中的按钮部件类,用于创建按钮控件。在 JsonFormatter 中使用了按钮来触发 JSON 格式化操作。

  • QVBoxLayout:Qt 中的垂直布局管理器,用于在窗口中垂直地排列部件。在 JsonFormatter 类的构造函数中使用了该布局来安排按钮和文本框的位置。

  • QTextEdit:Qt 中用于显示和编辑文本的控件。JsonFormatter 类中的输入和输出文本框均基于 QTextEdit 实现。

  • QJsonDocumentQJsonObject:Qt 提供的用于处理 JSON 数据的类。QJsonDocument 用于处理 JSON 文档,QJsonObject 用于表示 JSON 对象。在 JsonFormatter 类的 formatJson() 函数中使用这两个类来解析和处理 JSON 数据。

这些头文件提供了构建用户界面、创建按钮、设置布局以及处理和解析 JSON 数据所需的类和函数。它们为 JsonFormatter 类的实现提供了界面创建和 JSON 数据处理的基础功能。

类定义
class JsonFormatter : public QWidget {
    Q_OBJECT
public:
    explicit JsonFormatter(QWidget *parent = nullptr) : QWidget(parent) {
        // ...
    }

private slots:
    void formatJson() {
        // ...
    }

private:
    QTextEdit *inputTextEdit;
    QPushButton *formatButton;
    QTextEdit *outputTextEdit;
};
  • JsonFormatter 类继承自 QWidget,用于创建 JSON 格式化功能的界面部件。
  • 构造函数 JsonFormatter(QWidget *parent = nullptr):创建了 JSON 格式化功能所需的文本框、按钮和布局,初始化界面。
  • formatJson() 函数(槽函数):用于处理格式化按钮的点击事件,将输入的 JSON 数据格式化,并在输出文本框中显示。
格式化 JSON 数据
void formatJson() {
    QString inputText = inputTextEdit->toPlainText();
    QJsonParseError error{};
    QJsonDocument jsonDoc = QJsonDocument::fromJson(inputText.toUtf8(), &error);

    if (error.error != QJsonParseError::NoError) {
        outputTextEdit->setText("JSON 解析错误:" + error.errorString());
        return;
    }

    QJsonObject jsonObj = jsonDoc.object();
    QJsonDocument formattedJson(jsonObj);

    outputTextEdit->setText(formattedJson.toJson());
}
  • 获取输入文本框中的文本,并尝试将其解析为 JSON 格式的数据。
  • 使用 QJsonDocument::fromJson() 解析 JSON 数据,若解析失败则会设置 QJsonParseError,并在输出文本框中显示解析错误信息。
  • 如果解析成功,将解析后的 JSON 对象重新构建为 QJsonDocument,并使用 toJson() 方法将其格式化后的内容显示在输出文本框中。

总结

JsonFormatter 类利用 Qt 提供的 JSON 处理能力和界面构建功能,实现了简单的 JSON 格式化功能。它通过界面上的按钮触发格式化操作,将用户输入的 JSON 数据解析并重新排版显示,方便用户查看和理解 JSON 数据的结构和内容。

最后,在上面示例中,我们需要注意哪些地方?

JsonFormatter 示例中,有几个方面需要注意:

  1. 错误处理: 在解析 JSON 数据时,通过 QJsonParseError 进行错误检查,如果 JSON 格式错误,会在输出文本框中显示错误信息。这是一个很好的实践,能够向用户传达解析问题。

  2. 用户输入验证: 目前的代码并未对用户输入进行详细的验证,如果需要更严格的输入检查,可以添加额外的逻辑以确保输入数据的准确性和完整性。

  3. 界面交互性: 输入文本框与输出文本框的界面交互性有限。可以考虑在解析前对输入进行格式预处理、高亮显示错误部分或者给出更详细的错误信息。

  4. 使用 QJsonDocument 和 QJsonObject: 这两个类提供了方便的 JSON 数据处理方法。在实际项目中,可以进一步了解其功能,例如遍历 JSON 结构、修改数据等操作。(链接中是对应的文档地址)

  5. 错误处理和异常情况: 在解析 JSON 时,需要注意可能出现的异常情况,并在代码中进行适当的处理,确保程序的健壮性和稳定性。

  6. 用户体验: 为了更好的用户体验,可以考虑增加输入格式检测的功能,提供更友好的错误提示和辅助信息,让用户更容易理解并纠正输入。

  7. 界面布局与交互: 按钮和文本框的布局和样式对用户体验至关重要。优化布局和添加适当的反馈可以提升用户使用体验。


好了~ 本文就到这里了,感谢您的阅读,每天还有更多的实例学习文章等着你 🎆。别忘了点赞、收藏~ Thanks♪(・ω・)ノ 🍇。

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

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

相关文章

国内某知名半导体公司:实现虚拟化环境下的文件跨网安全交换

立足特定应用领域的创新型企业 上海某半导体公司是中国10大集成电路设计公司之一的子公司。该半导体公司是一家特色工艺集成电路芯片制造企业&#xff0c;专注模拟电路、功率器件所需的特色生产工艺研发与制造&#xff0c;。 该半导体公司不断追求创新&#xff0c;提高自身产…

《社交泛娱乐出海作战地图》加印领取啦!

全网都在找的、内容扎实形制精炼的行业首款 融云《社交泛娱乐出海作战地图》 响应需求&#xff0c;惊喜加印啦&#xff01; 久等的大家点击上图或阅读原文获取吧~ 关注【融云全球互联网通信云】了解更多 发布以来&#xff0c;《地图》两次加印均被抢购一空。 公众号后台、朋友…

rust-flexi_logger

flexi_logger 是字节开源的rust日志库。目前有log4rs、env_log 等库&#xff0c;综合比较下来&#xff0c;还是flexi_logger简单容易上手&#xff0c;而且自定义很方便&#xff0c;以及在效率方面感觉也会高&#xff0c;下篇文章我们来测试下。 下面来看下怎么使用 关注 vx gol…

基于M估计样本一致性算法的点云平面拟合

平面拟合 1、算法简介2、参考文献3、实现效果4、相关代码 1、算法简介 RANSAC 是在给定模型和距离阈值 T T T的情况下&#xff0c;通过寻找最小代价 C C C来确定内点数据并拟合模型。如式&#xff08;1&#xff09;所示的代价函数&#xff0c;当点到模型的距离 e e e小于阈值 T…

服务器运行情况及线上排查问题常用命令

一、top命令 指令行&#xff1a; top返回&#xff1a; 返回分为两部分 &#xff08;一&#xff09;系统概览&#xff0c;见图知意 以下是几个需要注意的参数 1、load average&#xff1a; 系统负载&#xff0c;即任务队列的平均长度。三个数值分别为 1分钟、5分钟、15分…

华为拆分零部件业务,长安入股,赛力斯接洽中

作者 |德新 编辑 |王博 11月26日&#xff0c;长安汽车官宣与华为在智能汽车零部件业务上的投资与合作&#xff1a; 华为拟成立一家新的公司&#xff0c;并将其在智能汽车解决方案业务上的核心技术和资源注入新公司&#xff0c;长安汽车及关联方有意投资该新公司。 参照目前长…

基于Webserver的工业数据采集控制

http协议 http简介 HTTP协议是Hyper Text Transfer Protocol&#xff08;超文本传输协议&#xff09;的缩写&#xff0c;是用于Web Browser&#xff08;浏览器&#xff09;到Web Server&#xff08;服务器&#xff09;进行数据交互的传输协议。 HTTP是应用层协议 HTTP是一个基于…

【日常总结】Swagger 3.0 + 集成 knife4j ,并设置header入参

一、场景 环境&#xff1a; 二、问题 思路 &#xff1a; 三、解决方案 &#xff08;推荐&#xff09; Stage 1&#xff1a;接入knife4j 依赖 Stage 2&#xff1a;修改 yaml 配置 Stage 3&#xff1a;修改 swagger 3 配置文件 Stage 4&#xff1a;查看效果 Swagger UI …

Spring源码解读之创建bean

本文章我们会解读一下Spring如何根据beanDefinition创建bean的&#xff1b; 代码入口&#xff1a; AnnotationConfigApplicationContext applicationContext new AnnotationConfigApplicationContext(AppConfig.class);applicationContext.refresh(); 当spring执行refresh(…

使用vscode中编写c语言——无法打开 源 文件 “stdlib.h“C/C++(1696)问题

出现这个问题原因如下&#xff1a; 1、没有下载编辑器或者是没有配置好该编辑器的环境变量。 可以通过如下方法检查是否安装并配置好编辑器&#xff1a;打开终端&#xff1a;按winR cmd&#xff0c;然后输入gcc-v&#xff0c;查看是否有mingw64编辑器&#xff0c;如下图是已经…

什么是yum?

&#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;推荐专栏1: &#x1f354;&#x1f35f;&#x1f32f;C语言初阶 &#x1f43b;推荐专栏2: &#x1f354;&#x1f35f;&#x1f32f;C语言进阶 &#x1f511;个人信条: &#x1f335;知行合一 &#x1f…

JAVA进阶之路JVM-2:类加载机制,类的生命周期,类加载过程,类加载时机,类加载器,双亲委派模型,对象创建过程

JVM类加载机制 类加载 ​ 在JVM虚拟机实现规范中&#xff0c;通过ClassLoader类加载把*.class字节码文件&#xff08;文件流&#xff09;加载到内存&#xff0c;并对字节码文件内容进行验证&#xff0c;准备&#xff0c;解析和初始化&#xff0c;最终形成可以被虚拟机直接使用…

易基因: MeRIP-seq等从m6A RNA甲基化角度揭示NFATc1对破骨细胞的调控机制|研究速递

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 双膦酸盐类药物是强效骨吸收抑制剂&#xff0c;是治疗骨质疏松症、多发性骨髓瘤、骨转移等疾病的首选药物。这些药物通过抑制甲羟戊酸通路和促进破骨细胞凋亡来促进骨吸收。双膦酸盐类药…

计算机网络:快速了解网络框架

文章目录 前言一、什么是Internet&#xff1f;1.从具体构成角度什么是协议&#xff1f; 2.从服务角度3小结 二、网络边缘1.采用网络设施面向连接服务&#xff08;TCP&#xff09;2.采用基础设施的无连接服务&#xff08;UDP&#xff09; 三、网络的核心1.电路交换2.分组交换3.分…

如何在外远程访问本地NAS威联通QNAP?

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;数据结构、Cpolar杂谈 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. 威联通安装cpolar内网穿透二. 内网穿透2.1 创建隧道2.2 测试公网远程访问 三.…

DDD全网最通俗易懂讲解(二)

领域事件相关案例 我来给你介绍一个保险承保业务过程中有关领域事件的案例。 一个保单的生成&#xff0c;经历了很多子域、业务状态变更和跨微服务业务数据的传递。这个过程会产生很多的领域事件&#xff0c;这些领域事件促成了保险业务数据、对象在不同的微服务和子域之间的…

数据库基础入门 — 关联查询

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 本…

docker容器运维操作命令

docker exec &#xff1a;在运行的容器中执行命令 docker exec [OPTIONS] CONTAINER COMMAND [ARG...] OPTIONS说明&#xff1a; -d :分离模式: 在后台运行 -i :即使没有附加也保持STDIN 打开 -t :分配一个伪终端docker ps : 列出容器 docker ps [OPTIONS] OPTIONS说明&#…

P8安全基本理论A001-CIA安全模型-使用PGP描述网络安全CIA模型之私密性、完整性案例

【教学资源名称】 CIA安全模型-使用PGP描述网络安全CIA模型之私密性、完整性案例 【预备知识】 在信息安全等级保护工作中&#xff0c;根据信息系统的机密性&#xff08;Confidentiality&#xff09;、完整性&#xff08;Integrity&#xff09;、可用性&#xff08;Availabilit…

MySQL的索引

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 目录 &#x1f324;️概念 &#x1f…