域名如何绑定网站,西宁做网站_君博先进,wordpress主题手机主题,百度的营销推广模式上篇文章#xff0c;我们用 Qt5 实现了在小工具箱中添加了《进制转换器功能》功能。为了继续丰富我们的工具箱#xff0c;今天我们就再增加一个平时经常用到的功能吧#xff0c;就是「 XML文本格式化 」功能。下面我们就来看看如何来规划开发一个这样的小功能并且添加到我们…上篇文章我们用 Qt5 实现了在小工具箱中添加了《进制转换器功能》功能。为了继续丰富我们的工具箱今天我们就再增加一个平时经常用到的功能吧就是「 XML文本格式化 」功能。下面我们就来看看如何来规划开发一个这样的小功能并且添加到我们的工具箱中吧。
老规矩先看效果
正确解析的效果 解析错误的效果 XML文本格式化功能概述
功能描述 XML格式化工具允许用户输入未格式化的XML文本并将其格式化为易于阅读的结构化形式。这个工具允许用户以清晰的方式查看和编辑XML数据提高了XML文档的可读性和可维护性。
功能需求
文本输入区域 提供一个文本框用于用户输入原始的未格式化XML文本。格式化按钮 提供一个按钮当用户点击时执行XML文本的格式化操作。格式化输出区域 显示格式化后的XML文本结果以便用户查看和复制到其他位置。清晰的显示效果 格式化后的XML文本应该以良好的缩进和层级结构显示以便用户更容易阅读和理解。
工作流程
用户在文本框中输入未格式化的XML文本。用户点击“格式化”按钮。系统执行XML文本的格式化操作。格式化后的XML文本显示在输出区域以清晰的缩进和层级结构呈现。
优势和价值
提升可读性 将XML文本格式化后使其更易于阅读和理解。简化编辑和维护 格式化的XML文档更容易编辑和维护减少错误和混淆。
注意事项
输入的XML文本应该是有效的不符合XML规范的文本可能会导致格式化错误。需要考虑处理可能存在的格式化异常或错误的情况向用户提供相应的反馈或提示。
这个功能对于需要处理或查看大量XML文本的用户或开发人员非常有用可以提高工作效率和准确性。
核心代码实现
现在进入正题我们如何实现一个格式化XML文本的功能而且这个功能将用一个按钮进行触发。首先我们创建一个名为 XmlFormatter 的新类并在 MyMainWindow 中添加一个按钮来显示和隐藏 XmlFormatter。
class XmlFormatter : public QWidget {
Q_OBJECT
public:explicit XmlFormatter(QWidget *parent nullptr) : QWidget(parent) {auto *layout new QVBoxLayout(this);inputTextEdit new QTextEdit(this);layout-addWidget(inputTextEdit);formatButton new QPushButton(格式化 XML, this);connect(formatButton, QPushButton::clicked, this, XmlFormatter::formatXml);layout-addWidget(formatButton);outputTextEdit new QTextEdit(this);outputTextEdit-setReadOnly(true);layout-addWidget(outputTextEdit);setLayout(layout);}private slots:void formatXml() {// 获取输入的XML文本QString inputText inputTextEdit-toPlainText();if (!inputText.isEmpty()) {// 使用 QXmlStreamReader 读取输入的 XML 文本QXmlStreamReader reader(inputText);QString formattedXml;int indentLevel 0;while (!reader.atEnd() !reader.hasError()) {if (reader.isStartElement()) {formattedXml getIndent(indentLevel) reader.name().toString() \n;indentLevel;} else if (reader.isEndElement()) {--indentLevel;formattedXml getIndent(indentLevel) / reader.name().toString() \n;} else if (reader.isCharacters() !reader.isWhitespace()) {formattedXml getIndent(indentLevel) reader.text().toString() \n;}reader.readNext();}if (reader.hasError()) {outputTextEdit-setText(XML 解析错误 reader.errorString());} else {outputTextEdit-setText(formattedXml);}} else {// 如果输入为空则清空输出区域outputTextEdit-clear();}}static QString getIndent(int level) {return QString(level * 4, ); // 4空格作为缩进}private:QTextEdit *inputTextEdit;QPushButton *formatButton;QTextEdit *outputTextEdit;
};然后在 MyMainWindow 类中添加一个按钮和 XmlFormatter 对象并在槽函数 toggleXmlFormatter 中切换它的显示状态。
class MyMainWindow : public QWidget {
Q_OBJECT
public:explicit MyMainWindow(QWidget *parent nullptr) : QWidget(parent) {setWindowTitle(天河工具箱);auto *layout new QVBoxLayout(this);// ... 之前的按钮auto *xmlFormatterButton new QPushButton(显示XML格式化);xmlFormatterButton-setObjectName(xmlFormatterButton);connect(xmlFormatterButton, QPushButton::clicked, this, MyMainWindow::toggleXmlFormatter);xmlFormatter new XmlFormatter(this);xmlFormatter-hide();layout-addWidget(xmlFormatter);layout-addWidget(xmlFormatterButton);setLayout(layout);}private slots:void toggleXmlFormatter() {auto* curButton findChildQPushButton*(xmlFormatterButton);if (xmlFormatter-isHidden()) {if (curButton) {curButton-setText(隐藏XML格式化);}xmlFormatter-show();} else {if (curButton) {curButton-setText(显示XML格式化);}xmlFormatter-hide();}}private:XmlFormatter *xmlFormatter;// ... 其他对象
};这样你现在就有一个名为 XmlFormatter 的新类它具有格式化XML文本的功能并且通过在 MyMainWindow 中添加一个按钮可以控制其显示和隐藏。 核心代码拆分讲解
第一部分
class XmlFormatter : public QWidget {
Q_OBJECT
public:explicit XmlFormatter(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, XmlFormatter::formatXml);layout-addWidget(formatButton);outputTextEdit new QTextEdit(this);outputTextEdit-setReadOnly(true);layout-addWidget(outputTextEdit);setLayout(layout);}XmlFormatter是一个QWidget的子类用于格式化XML文本。构造函数XmlFormatter创建了一个垂直布局layout将各个控件嵌套在其中。inputTextEdit是一个QTextEdit控件用于用户输入XML文本。formatButton是一个QPushButton按钮点击后将触发格式化XML文本的槽函数。outputTextEdit是一个只读的QTextEdit用于显示格式化后的XML文本。
第二部分
当点击格式化按钮时formatXml() 槽函数被触发。它首先获取用户在输入文本框中输入的XML文本。接着使用 QXmlStreamReader 对象来读取输入的XML文本。在这段代码中QXmlStreamReader 用于遍历XML文本的各个部分。
void formatXml() {QString inputText inputTextEdit-toPlainText();// 使用 QXmlStreamReader 读取输入的 XML 文本QXmlStreamReader reader(inputText);QString formattedXml;int indentLevel 0;while (!reader.atEnd() !reader.hasError()) {if (reader.isStartElement()) {formattedXml getIndent(indentLevel) reader.name().toString() \n;indentLevel;} else if (reader.isEndElement()) {--indentLevel;formattedXml getIndent(indentLevel) / reader.name().toString() \n;} else if (reader.isCharacters() !reader.isWhitespace()) {formattedXml getIndent(indentLevel) reader.text().toString() \n;}reader.readNext();}if (reader.hasError()) {outputTextEdit-setText(XML 解析错误 reader.errorString());} else {outputTextEdit-setText(formattedXml);}
}在while循环中程序首先检查当前的XML事件。当它遇到一个开始元素时它会在 formattedXml 中添加该元素的标签并增加缩进级别。当它遇到一个结束元素时它会在 formattedXml 中添加该元素的结束标签并减少缩进级别。最后当遇到元素内容characters时它会将内容添加到 formattedXml 中并根据缩进级别进行缩进。
QString getIndent(int level) {return QString(level * 4, ); // 4空格作为缩进
}getIndent 函数用于返回指定级别的缩进字符串它返回一个由指定数量空格组成的字符串以此作为 XML 格式化中的缩进。
最后如果 QXmlStreamReader 遇到错误它会将错误消息显示在输出文本框中否则将格式化后的XML显示在输出文本框中。 讲解完毕下面是完整代码复制到本地跑一跑吧~
#include QApplication
#include QWidget
#include QPushButton
#include QVBoxLayout
#include QMessageBox
#include QDebug
#include QListWidget
#include QClipboard
#include QMimeData
#include QTextEdit
#include QJsonDocument
#include QJsonObject
#include QDateTime
#include QLabel
#include QComboBox
#include QLineEdit
#include QXmlStreamReader#define myApp (dynamic_castQApplication *(QCoreApplication::instance()))class XmlFormatter : public QWidget {
Q_OBJECT
public:explicit XmlFormatter(QWidget *parent nullptr) : QWidget(parent) {auto *layout new QVBoxLayout(this);inputTextEdit new QTextEdit(this);layout-addWidget(inputTextEdit);formatButton new QPushButton(格式化 XML, this);connect(formatButton, QPushButton::clicked, this, XmlFormatter::formatXml);layout-addWidget(formatButton);outputTextEdit new QTextEdit(this);outputTextEdit-setReadOnly(true);layout-addWidget(outputTextEdit);setLayout(layout);}private slots:void formatXml() {// 获取输入的XML文本QString inputText inputTextEdit-toPlainText();if (!inputText.isEmpty()) {// 使用 QXmlStreamReader 读取输入的 XML 文本QXmlStreamReader reader(inputText);QString formattedXml;int indentLevel 0;while (!reader.atEnd() !reader.hasError()) {if (reader.isStartElement()) {formattedXml getIndent(indentLevel) reader.name().toString() \n;indentLevel;} else if (reader.isEndElement()) {--indentLevel;formattedXml getIndent(indentLevel) / reader.name().toString() \n;} else if (reader.isCharacters() !reader.isWhitespace()) {formattedXml getIndent(indentLevel) reader.text().toString() \n;}reader.readNext();}if (reader.hasError()) {outputTextEdit-setText(XML 解析错误 reader.errorString());} else {outputTextEdit-setText(formattedXml);}} else {// 如果输入为空则清空输出区域outputTextEdit-clear();}}static QString getIndent(int level) {return QString(level * 4, ); // 4空格作为缩进}private:QTextEdit *inputTextEdit;QPushButton *formatButton;QTextEdit *outputTextEdit;
};class NumberBaseConverter : public QWidget {
Q_OBJECT
public:explicit NumberBaseConverter(QWidget *parent nullptr) : QWidget(parent) {auto *layout new QVBoxLayout(this);// 横向排列的输入框和选择框auto *horizontalLayout new QHBoxLayout();// 创建输入框并添加到水平布局inputLineEdit new QLineEdit(this);horizontalLayout-addWidget(inputLineEdit);// 连接输入框的文本变化信号到槽函数connect(inputLineEdit, QLineEdit::textChanged, this, NumberBaseConverter::convertNumber);// 创建下拉选择框并添加到水平布局baseComboBox new QComboBox(this);baseComboBox-addItem(二进制);baseComboBox-addItem(八进制);baseComboBox-addItem(十进制);baseComboBox-addItem(十六进制);horizontalLayout-addWidget(baseComboBox);// 将水平布局添加到垂直布局layout-addLayout(horizontalLayout);// 创建四个只读的输出框并添加到垂直布局binaryOutput new QLineEdit(this);binaryOutput-setReadOnly(true);layout-addWidget(binaryOutput);octalOutput new QLineEdit(this);octalOutput-setReadOnly(true);layout-addWidget(octalOutput);decimalOutput new QLineEdit(this);decimalOutput-setReadOnly(true);layout-addWidget(decimalOutput);hexOutput new QLineEdit(this);hexOutput-setReadOnly(true);layout-addWidget(hexOutput);// 连接下拉选择框的选择变化信号到槽函数并进行初始转换connect(baseComboBox, QOverloadint::of(QComboBox::currentIndexChanged), this, NumberBaseConverter::convertNumber);convertNumber(); // 初始转换setLayout(layout); // 设置整体布局}private slots:void convertNumber() {QString inputText inputLineEdit-text();bool ok;int base baseComboBox-currentIndex();if (!inputText.isEmpty()) {// 根据所选进制进行转换if (base 0) {int number inputText.toInt(ok, 2); // 二进制转十进制if (ok) {binaryOutput-setText(inputText);octalOutput-setText(QString::number(number, 8));decimalOutput-setText(QString::number(number));hexOutput-setText(QString::number(number, 16).toUpper());}} else if (base 1) {// 八进制转换int number inputText.toInt(ok, 8);if (ok) {binaryOutput-setText(QString::number(number, 2));octalOutput-setText(inputText);decimalOutput-setText(QString::number(number));hexOutput-setText(QString::number(number, 16).toUpper());}} else if (base 2) {// 十进制转换int number inputText.toInt(ok, 10);if (ok) {binaryOutput-setText(QString::number(number, 2));octalOutput-setText(QString::number(number, 8));decimalOutput-setText(inputText);hexOutput-setText(QString::number(number, 16).toUpper());}} else if (base 3) {// 十六进制转换int number inputText.toInt(ok, 16);if (ok) {binaryOutput-setText(QString::number(number, 2));octalOutput-setText(QString::number(number, 8));decimalOutput-setText(QString::number(number));hexOutput-setText(inputText.toUpper());}}} else {// 如果输入为空则清空输出binaryOutput-clear();octalOutput-clear();decimalOutput-clear();hexOutput-clear();}}private:QLineEdit *inputLineEdit;QComboBox *baseComboBox;QLineEdit *binaryOutput;QLineEdit *octalOutput;QLineEdit *decimalOutput;QLineEdit *hexOutput;
};class PlaceholderTextEdit : public QWidget {
Q_OBJECT
public:explicit PlaceholderTextEdit(const QString placeholderText, QWidget *parent nullptr) : QWidget(parent) {auto *layout new QVBoxLayout(this);placeholderLabel new QLabel(placeholderText, this);layout-addWidget(placeholderLabel);textEdit new QTextEdit(this);layout-addWidget(textEdit);connect(textEdit, QTextEdit::textChanged, this, PlaceholderTextEdit::checkPlaceholder);checkPlaceholder(); // 初始检查setLayout(layout);}QString getText() const {return textEdit-toPlainText();}private slots:void checkPlaceholder() {placeholderLabel-setVisible(textEdit-toPlainText().isEmpty());}private:QLabel *placeholderLabel;QTextEdit *textEdit;
};class DateTimeTimestampConverter : public QWidget {
Q_OBJECT
public:explicit DateTimeTimestampConverter(QWidget *parent nullptr) : QWidget(parent) {auto *layout new QVBoxLayout(this);inputTextEdit new PlaceholderTextEdit(在此输入日期时间或时间戳, this);layout-addWidget(inputTextEdit);convertToTimestampButton new QPushButton(日期时间转时间戳, this);connect(convertToTimestampButton, QPushButton::clicked, this, DateTimeTimestampConverter::convertToTimestamp);layout-addWidget(convertToTimestampButton);convertToDateTimeButton new QPushButton(时间戳转日期时间, this);connect(convertToDateTimeButton, QPushButton::clicked, this, DateTimeTimestampConverter::convertToDateTime);layout-addWidget(convertToDateTimeButton);outputTextEdit new QTextEdit(this);outputTextEdit-setReadOnly(true);layout-addWidget(outputTextEdit);setLayout(layout);}private slots:void convertToTimestamp() {QString inputText inputTextEdit-getText();QDateTime dateTime QDateTime::fromString(inputText, yyyy-MM-dd HH:mm:ss);if (dateTime.isValid()) {qint64 timestamp dateTime.toSecsSinceEpoch();outputTextEdit-setText(QString::number(timestamp));} else {outputTextEdit-setText(无效的日期时间格式);}}void convertToDateTime() {QString inputText inputTextEdit-getText();bool ok;qint64 timestamp inputText.toLongLong(ok);if (ok) {QDateTime dateTime;dateTime.setSecsSinceEpoch(timestamp);outputTextEdit-setText(时间戳 inputText 对应的日期时间是 dateTime.toString(yyyy-MM-dd HH:mm:ss));} else {outputTextEdit-setText(无效的时间戳格式);}}private:QPushButton *convertToTimestampButton;QPushButton *convertToDateTimeButton;QTextEdit *outputTextEdit;PlaceholderTextEdit *inputTextEdit;
};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(显示管理粘贴板记录功能);clipboardButton-setObjectName(clipboardButton);connect(clipboardButton, QPushButton::clicked, this, MyMainWindow::toggleClipboardManager);clipboardManager new ClipboardManager(this);clipboardManager-hide();layout-addWidget(clipboardManager);layout-addWidget(clipboardButton);auto *jsonFormatButton new QPushButton(显示格式化 JSON 功能);jsonFormatButton-setObjectName(jsonFormatButton);connect(jsonFormatButton, QPushButton::clicked, this, MyMainWindow::toggleJsonFormatter);jsonFormatter new JsonFormatter(this);jsonFormatter-hide();layout-addWidget(jsonFormatter);layout-addWidget(jsonFormatButton);auto *timestampConverterButton new QPushButton(显示时间戳转换功能);timestampConverterButton-setObjectName(timestampConverterButton);connect(timestampConverterButton, QPushButton::clicked, this, MyMainWindow::toggleDateTimeTimestampConverter);timestampConverter new DateTimeTimestampConverter(this);timestampConverter-hide();layout-addWidget(timestampConverter);layout-addWidget(timestampConverterButton);auto *numberBaseConverterButton new QPushButton(显示进制转换功能);numberBaseConverterButton-setObjectName(numberBaseConverterButton);connect(numberBaseConverterButton, QPushButton::clicked, this, MyMainWindow::toggleNumberBaseConverter);numberBaseConverter new NumberBaseConverter(this);numberBaseConverter-hide();layout-addWidget(numberBaseConverter);layout-addWidget(numberBaseConverterButton);auto *xmlFormatterButton new QPushButton(显示XML格式化功能);xmlFormatterButton-setObjectName(xmlFormatterButton);connect(xmlFormatterButton, QPushButton::clicked, this, MyMainWindow::toggleXmlFormatter);xmlFormatter new XmlFormatter(this);xmlFormatter-hide();layout-addWidget(xmlFormatter);layout-addWidget(xmlFormatterButton);setLayout(layout);}private slots:void toggleClipboardManager() {auto* curButton findChildQPushButton*(clipboardButton);if (clipboardManager-isHidden()) {if (curButton) {curButton-setText(隐藏管理粘贴板记录);}clipboardManager-show();} else {if (curButton) {curButton-setText(显示管理粘贴板记录);}clipboardManager-hide();}}void toggleJsonFormatter() {auto* curButton findChildQPushButton*(jsonFormatButton);if (jsonFormatter-isHidden()) {if (curButton) {curButton-setText(隐藏格式化 JSON);}jsonFormatter-show();} else {if (curButton) {curButton-setText(显示格式化 JSON);}jsonFormatter-hide();}}void toggleDateTimeTimestampConverter() {auto* curButton findChildQPushButton*(timestampConverterButton);if (timestampConverter-isHidden()) {if (curButton) {curButton-setText(隐藏时间戳转换);}timestampConverter-show();} else {if (curButton) {curButton-setText(显示时间戳转换);}timestampConverter-hide();}}void toggleNumberBaseConverter() {auto* curButton findChildQPushButton*(numberBaseConverterButton);if (numberBaseConverter-isHidden()) {if (curButton) {curButton-setText(隐藏进制转换器);}numberBaseConverter-show();} else {if (curButton) {curButton-setText(显示进制转换器);}numberBaseConverter-hide();}}void toggleXmlFormatter() {auto* curButton findChildQPushButton*(xmlFormatterButton);if (xmlFormatter-isHidden()) {if (curButton) {curButton-setText(隐藏XML格式化);}xmlFormatter-show();} else {if (curButton) {curButton-setText(显示XML格式化);}xmlFormatter-hide();}}private:ClipboardManager *clipboardManager;JsonFormatter *jsonFormatter;DateTimeTimestampConverter *timestampConverter;NumberBaseConverter *numberBaseConverter;XmlFormatter *xmlFormatter;
};int main(int argc, char *argv[]) {QApplication a(argc, argv);MyMainWindow mainWindow;mainWindow.show();return QApplication::exec();
}#include main.moc
经过这十二篇的文章讲解我们的工具箱也逐渐成型了看起来也像那么回事了。 后续我们继续为这个工具箱添砖加瓦然后再粉饰粉饰界面它就能出去见人了~
往期文章一览
C学习之路一什么是C如何循序渐进的学习C【纯干货】
C学习之路二C如何实现一个超简单的学生信息管理系统C示例和小项目实例
C学习之路三解析讲解超简单学生信息管理系统代码知识点 - 《根据实例学知识》
C学习之路四C 实现简单的待办事项列表命令行应用 - 示例代码拆分讲解
C学习之路五C 实现简单的文件管理系统命令行应用 - 示例代码拆分讲解
C学习之路六C 实现简单的工具箱系统命令行应用 - 示例代码拆分讲解
C学习之路七C 实现简单的Qt界面消息弹框、按钮点击事件监听- 示例代码拆分讲解
C学习之路八C 用Qt5实现一个工具箱增加一个粘贴板记录管理功能- 示例代码拆分讲解
C学习之路九C 用Qt5实现一个工具箱增加一个JSON数据格式化功能- 示例代码拆分讲解
C学习之路十C 用Qt5实现一个工具箱增加一个时间戳转换功能- 示例代码拆分讲解
C学习之路十一C 用Qt5实现一个工具箱增加一个进制转换器功能- 示例代码拆分讲解 好了~ 本文就到这里了感谢您的阅读每天还有更多的实例学习文章等着你 。别忘了点赞、收藏~ Thanks♪(ω) 。