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

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

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

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


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

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天河书阁 VicRestart

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值