C++学习之路(十五)C++ 用Qt5实现一个工具箱(增加16进制颜色码转换和屏幕颜色提取功能)- 示例代码拆分讲解

上篇文章,我们用 Qt5 实现了在小工具箱中添加了《Base64图片编码预览功能》功能。为了继续丰富我们的工具箱,今天我们就再增加两个平时经常用到的功能吧,就是「 16进制颜色码转RGB文本 」和 「屏幕颜色提取」功能。下面我们就来看看如何来规划开发这样的小功能并且添加到我们的工具箱中吧。

老规矩,先上图

16进制转RGB

在这里插入图片描述

RGB转16进制

在这里插入图片描述

屏幕颜色提取

在这里插入图片描述

功能概述:颜色码转换和屏幕颜色提取

  1. 颜色码转换功能

    • 输入:支持输入RGB颜色代码或16进制颜色代码。
    • 输出:转换为另一种格式的颜色代码。
    • 操作:支持从RGB转换为16进制和反之转换。
  2. 屏幕颜色提取功能

    • 操作:捕获屏幕上鼠标位置的颜色信息。
    • 展示:显示提取到的颜色,包括16进制颜色代码和颜色预览。
    • 交互:启动功能后,可以在屏幕上移动鼠标以实时获取不同位置的颜色。
    • 终止:点击特定键盘按键(例如按下Tab键)以停止捕获。

需求概述:

  1. 颜色码转换功能

    • 用户友好:提供清晰的界面,支持输入RGB或16进制颜色代码。
    • 格式转换:允许用户在RGB和16进制颜色代码之间进行转换。
    • 展示结果:将转换后的颜色代码显示给用户。
  2. 屏幕颜色提取功能

    • 启动捕获:点击按钮启动颜色捕获功能。
    • 显示颜色:在界面上显示捕获到的颜色代码和颜色预览。
    • 实时更新:随着鼠标移动,实时显示不同位置的颜色。
    • 停止捕获:通过特定操作(例如按下Tab键)停止捕获颜色。
    • 异常处理:处理未找到屏幕或捕获颜色失败的情况。

这样的功能旨在提供一个便捷的界面,允许用户在RGB和16进制颜色代码之间自由转换,并且能够在屏幕上捕获颜色以获取准确的颜色信息。


核心代码实现

class ColorConverter : public QWidget {
Q_OBJECT
public:explicit ColorConverter(QWidget *parent = nullptr) : QWidget(parent) {// 在构造函数中初始化定时器colorTimer = new QTimer(this);colorTimer->setInterval(100); // 设置定时器间隔为100毫秒connect(colorTimer, &QTimer::timeout, this, &ColorConverter::extractScreenColor);auto *layout = new QVBoxLayout(this);// 创建颜色值转换部分的输入框和按钮colorInput = new QLineEdit(this);layout->addWidget(colorInput);convertButton = new QPushButton("16进制转RGB", this);connect(convertButton, &QPushButton::clicked, this, &ColorConverter::convertToRgbColor);layout->addWidget(convertButton);convertButton = new QPushButton("RGB转16进制", this);connect(convertButton, &QPushButton::clicked, this, &ColorConverter::convertToHexColor);layout->addWidget(convertButton);convertedColorOutput = new QTextEdit(this);convertedColorOutput->setReadOnly(true);layout->addWidget(convertedColorOutput);// 创建屏幕颜色提取器部分的按钮和显示框extractColorButton = new QPushButton("开始提取屏幕颜色", this);connect(extractColorButton, &QPushButton::clicked, this, &ColorConverter::startColorCapture);layout->addWidget(extractColorButton);// 创建用于存放颜色块和颜色输出的网格布局auto *colorBlockLayout = new QGridLayout();// 创建颜色输出screenColorOutput = new QLabel(this);screenColorOutput->setFixedSize(200, 90);screenColorOutput->setAlignment(Qt::AlignCenter);screenColorOutput->setStyleSheet("border: 1px solid #ddd");colorBlockLayout->addWidget(screenColorOutput, 0, 0); // 将颜色输出放在网格布局的左上角// 创建颜色块screenColorBlock = new QLabel(this);screenColorBlock->setFixedSize(30, 30); // 设置颜色块大小screenColorBlock->setStyleSheet("border: 1px solid #ddd");colorBlockLayout->addWidget(screenColorBlock, 0, 0, Qt::AlignTop | Qt::AlignRight); // 将颜色块放在颜色输出的右上角layout->addLayout(colorBlockLayout);setLayout(layout);installEventFilter(this); // 安装事件过滤器以捕获鼠标事件}protected slots:void convertToHexColor() {// 从输入框获取颜色值QString colorText = colorInput->text();// 按逗号分隔RGB文本QStringList rgbValues = colorText.split(',');if (rgbValues.size() == 3) {// 获取R、G和B的值int red = rgbValues[0].toInt();int green = rgbValues[1].toInt();int blue = rgbValues[2].toInt();// 将RGB值转换为16进制字符串QString hexRed = QString("%1").arg(red, 2, 16, QChar('0')).toUpper();QString hexGreen = QString("%1").arg(green, 2, 16, QChar('0')).toUpper();QString hexBlue = QString("%1").arg(blue, 2, 16, QChar('0')).toUpper();// 构建16进制颜色代码文本QString hexText = QString("#%1%2%3").arg(hexRed).arg(hexGreen).arg(hexBlue);convertedColorOutput->setText(hexText);} else {// 处理无效颜色输入的情况convertedColorOutput->setText("Invalid color input");}}void convertToRgbColor() {// 从输入框获取颜色值QString colorText = colorInput->text();QColor color(colorText);if (color.isValid()) {// 获取16进制颜色码的红、绿、蓝通道值int red = color.red();int green = color.green();int blue = color.blue();// 构建RGB颜色代码文本QString outputText = QString("RGB(%1, %2, %3)").arg(red).arg(green).arg(blue);convertedColorOutput->setText(outputText);} else {// 处理无效颜色输入的情况convertedColorOutput->setText("Invalid color input");}}// 开始捕获颜色的槽函数void startColorCapture() {extractColorButton->setText("请开始移动鼠标 按Tab键终止取色");colorTimer->start();}void extractScreenColor() {QPoint cursorPos = QCursor::pos();QScreen *screen = QGuiApplication::screenAt(cursorPos);if (screen) {QPixmap screenshot = screen->grabWindow(0, cursorPos.x(), cursorPos.y(), 1, 1);if (!screenshot.isNull()) {QColor color = screenshot.toImage().pixel(0, 0);QString colorText = QString("Screen Color: #%1").arg(color.name().mid(1));screenColorOutput->setText(colorText);QString styleSheet = QString("background-color: %1; border: 1px solid #ddd;").arg(color.name());screenColorBlock->setStyleSheet(styleSheet);} else {screenColorOutput->setText("Failed to grab screen color");}} else {screenColorOutput->setText("No screen found at the cursor position");}}// 停止捕获颜色的槽函数void stopColorCapture() {colorTimer->stop();extractColorButton->setText("开始提取屏幕颜色");}
protected:// 捕获松开Tab按键事件bool eventFilter(QObject *watched, QEvent *event) override {if (event->type() == QEvent::WindowDeactivate || event->type() == QEvent::KeyRelease) {stopColorCapture();return true;}return QObject::eventFilter(watched, event);}private:QLineEdit *colorInput;QPushButton *convertButton;QTextEdit *convertedColorOutput;QPushButton *extractColorButton;QLabel *screenColorOutput;QLabel *screenColorBlock;QTimer *colorTimer;
};

核心代码讲解

让我们逐段解析 ColorConverter 类的代码。

class ColorConverter : public QWidget {
Q_OBJECT
public:explicit ColorConverter(QWidget *parent = nullptr) : QWidget(parent) {// 在构造函数中初始化定时器colorTimer = new QTimer(this);colorTimer->setInterval(100); // 设置定时器间隔为100毫秒connect(colorTimer, &QTimer::timeout, this, &ColorConverter::extractScreenColor);auto *layout = new QVBoxLayout(this);// 创建颜色值转换部分的输入框和按钮colorInput = new QLineEdit(this);layout->addWidget(colorInput);// ...(略)installEventFilter(this); // 安装事件过滤器以捕获鼠标事件}// ...(略)
};
  1. 构造函数与定时器初始化:构造函数中创建了一个 ColorConverter 对象,并初始化了一个定时器 colorTimer。这个定时器用于每 100 毫秒触发一次屏幕颜色提取功能,并与 extractScreenColor 函数连接。

  2. 界面布局初始化:在构造函数中,使用了垂直布局管理器 QVBoxLayout,并添加了颜色输入框到布局中。

  3. 事件过滤器安装installEventFilter(this) 安装了一个事件过滤器来监视该对象所接收到的事件。在这个场景中,它用于捕获鼠标事件以停止颜色提取。

转换函数

void convertToHexColor() {// 获取输入框中的颜色值,转换为16进制// ...
}void convertToRgbColor() {// 获取输入框中的颜色值,转换为RGB格式// ...
}
  • QLineEdit 和 QTextEdit:分别用于输入和显示颜色值,convertToHexColor 和 convertToRgbColor 函数用于颜色转换。

屏幕颜色提取器

void startColorCapture() {// 开始捕获颜色的槽函数// ...
}void extractScreenColor() {// 提取屏幕颜色的槽函数// ...
}void stopColorCapture() {// 停止颜色捕获的槽函数// ...
}
  • QPushButton 和 QLabel:extractColorButton 用于启动颜色捕获,screenColorOutput 和 screenColorBlock 用于显示屏幕颜色信息。

事件过滤器

bool eventFilter(QObject *watched, QEvent *event) override {// 事件过滤器,捕获键盘事件以终止颜色捕获// ...
}
  • QObject 和 QEvent:eventFilter 捕获键盘事件,当用户按下 Tab 键松开时终止颜色捕获。

总结

主要利用了 Qt 中的 QWidget、QObject、QTimer、QLineEdit、QPushButton、QTextEdit、QLabel 等部件,以及事件过滤器功能来实现颜色转换和屏幕颜色提取的功能。按钮的点击触发不同的槽函数,展示了转换后的颜色信息或从屏幕获取的颜色信息。同时,通过事件过滤器监听键盘事件,以实现终止屏幕颜色提取的功能。


讲解完毕,下面是完整代码,复制到本地跑一跑吧~

#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>
#include <QFile>
#include <QFileDialog>
#include <QScreen>
#include <QCursor>
#include <QPoint>
#include <QGuiApplication>
#include <QPixmap>
#include <QHBoxLayout>
#include <QThread>
#include <QMouseEvent>
#include <QTimer>#define myApp (dynamic_cast<QApplication *>(QCoreApplication::instance()))class ColorConverter : public QWidget {
Q_OBJECT
public:explicit ColorConverter(QWidget *parent = nullptr) : QWidget(parent) {// 在构造函数中初始化定时器colorTimer = new QTimer(this);colorTimer->setInterval(100); // 设置定时器间隔为100毫秒connect(colorTimer, &QTimer::timeout, this, &ColorConverter::extractScreenColor);auto *layout = new QVBoxLayout(this);// 创建颜色值转换部分的输入框和按钮colorInput = new QLineEdit(this);layout->addWidget(colorInput);convertButton = new QPushButton("16进制转RGB", this);connect(convertButton, &QPushButton::clicked, this, &ColorConverter::convertToRgbColor);layout->addWidget(convertButton);convertButton = new QPushButton("RGB转16进制", this);connect(convertButton, &QPushButton::clicked, this, &ColorConverter::convertToHexColor);layout->addWidget(convertButton);convertedColorOutput = new QTextEdit(this);convertedColorOutput->setReadOnly(true);layout->addWidget(convertedColorOutput);// 创建屏幕颜色提取器部分的按钮和显示框extractColorButton = new QPushButton("开始提取屏幕颜色", this);connect(extractColorButton, &QPushButton::clicked, this, &ColorConverter::startColorCapture);layout->addWidget(extractColorButton);// 创建用于存放颜色块和颜色输出的网格布局auto *colorBlockLayout = new QGridLayout();// 创建颜色输出screenColorOutput = new QLabel(this);screenColorOutput->setFixedSize(200, 90);screenColorOutput->setAlignment(Qt::AlignCenter);screenColorOutput->setStyleSheet("border: 1px solid #ddd");colorBlockLayout->addWidget(screenColorOutput, 0, 0); // 将颜色输出放在网格布局的左上角// 创建颜色块screenColorBlock = new QLabel(this);screenColorBlock->setFixedSize(30, 30); // 设置颜色块大小screenColorBlock->setStyleSheet("border: 1px solid #ddd");colorBlockLayout->addWidget(screenColorBlock, 0, 0, Qt::AlignTop | Qt::AlignRight); // 将颜色块放在颜色输出的右上角layout->addLayout(colorBlockLayout);setLayout(layout);installEventFilter(this); // 安装事件过滤器以捕获鼠标事件}protected slots:void convertToHexColor() {// 从输入框获取颜色值QString colorText = colorInput->text();// 按逗号分隔RGB文本QStringList rgbValues = colorText.split(',');if (rgbValues.size() == 3) {// 获取R、G和B的值int red = rgbValues[0].toInt();int green = rgbValues[1].toInt();int blue = rgbValues[2].toInt();// 将RGB值转换为16进制字符串QString hexRed = QString("%1").arg(red, 2, 16, QChar('0')).toUpper();QString hexGreen = QString("%1").arg(green, 2, 16, QChar('0')).toUpper();QString hexBlue = QString("%1").arg(blue, 2, 16, QChar('0')).toUpper();// 构建16进制颜色代码文本QString hexText = QString("#%1%2%3").arg(hexRed).arg(hexGreen).arg(hexBlue);convertedColorOutput->setText(hexText);} else {// 处理无效颜色输入的情况convertedColorOutput->setText("Invalid color input");}}void convertToRgbColor() {// 从输入框获取颜色值QString colorText = colorInput->text();QColor color(colorText);if (color.isValid()) {// 获取16进制颜色码的红、绿、蓝通道值int red = color.red();int green = color.green();int blue = color.blue();// 构建RGB颜色代码文本QString outputText = QString("RGB(%1, %2, %3)").arg(red).arg(green).arg(blue);convertedColorOutput->setText(outputText);} else {// 处理无效颜色输入的情况convertedColorOutput->setText("Invalid color input");}}// 开始捕获颜色的槽函数void startColorCapture() {extractColorButton->setText("请开始移动鼠标 按Tab键终止取色");colorTimer->start();}void extractScreenColor() {QPoint cursorPos = QCursor::pos();QScreen *screen = QGuiApplication::screenAt(cursorPos);if (screen) {QPixmap screenshot = screen->grabWindow(0, cursorPos.x(), cursorPos.y(), 1, 1);if (!screenshot.isNull()) {QColor color = screenshot.toImage().pixel(0, 0);QString colorText = QString("Screen Color: #%1").arg(color.name().mid(1));screenColorOutput->setText(colorText);QString styleSheet = QString("background-color: %1; border: 1px solid #ddd;").arg(color.name());screenColorBlock->setStyleSheet(styleSheet);} else {screenColorOutput->setText("Failed to grab screen color");}} else {screenColorOutput->setText("No screen found at the cursor position");}}// 停止捕获颜色的槽函数void stopColorCapture() {colorTimer->stop();extractColorButton->setText("开始提取屏幕颜色");}
protected:// 捕获松开Tab按键事件bool eventFilter(QObject *watched, QEvent *event) override {if (event->type() == QEvent::WindowDeactivate || event->type() == QEvent::KeyRelease) {stopColorCapture();return true;}return QObject::eventFilter(watched, event);}private:QLineEdit *colorInput;QPushButton *convertButton;QTextEdit *convertedColorOutput;QPushButton *extractColorButton;QLabel *screenColorOutput;QLabel *screenColorBlock;QTimer *colorTimer;
};class Base64ImageConverter : public QWidget {
Q_OBJECT
public:explicit Base64ImageConverter(QWidget *parent = nullptr) : QWidget(parent) {auto *layout = new QVBoxLayout(this);selectImageButton = new QPushButton("选择图片", this);connect(selectImageButton, &QPushButton::clicked, this, &Base64ImageConverter::selectImage);layout->addWidget(selectImageButton);imagePathTextEdit = new QTextEdit(this);imagePathTextEdit->setReadOnly(true);layout->addWidget(imagePathTextEdit);convertToBase64Button = new QPushButton("转换为Base64编码", this);connect(convertToBase64Button, &QPushButton::clicked, this, &Base64ImageConverter::convertToBase64);layout->addWidget(convertToBase64Button);base64OutputTextEdit = new QTextEdit(this);base64OutputTextEdit->setAcceptRichText(false);layout->addWidget(base64OutputTextEdit);convertToImagePreviewButton = new QPushButton("Base64编码转图片预览", this);connect(convertToImagePreviewButton, &QPushButton::clicked, this, &Base64ImageConverter::convertToImagePreview);layout->addWidget(convertToImagePreviewButton);imagePreviewLabel = new QLabel(this);imagePreviewLabel->setFixedHeight(200); // 设置图片高度为 200layout->addWidget(imagePreviewLabel);setLayout(layout);}private slots:void selectImage() {// 创建文件对话框用于选择图片文件QString imagePath = QFileDialog::getOpenFileName(this, tr("选择图片"), "", tr("Images (*.png *.jpg *.bmp)"));// 如果用户选择了图片文件,则显示文件路径if (!imagePath.isEmpty()) {imagePathTextEdit->setText(imagePath);selectedImagePath = imagePath;}}void convertToBase64() {if (selectedImagePath.isEmpty()) {QMessageBox::warning(this, "警告", "请先选择图片");return;}// 读取选定图片文件的内容QFile file(selectedImagePath);if (file.open(QIODevice::ReadOnly)) {QByteArray imageData = file.readAll();QString base64Data = imageData.toBase64();base64OutputTextEdit->setText(base64Data);} else {QMessageBox::critical(this, "错误", "无法读取图片文件");}}void convertToImagePreview() {QString base64Data = base64OutputTextEdit->toPlainText().toUtf8();if (base64Data.isEmpty()) {QMessageBox::warning(this, "警告", "请先转换为Base64编码");return;}// 从Base64数据创建QImage并显示在标签中QByteArray byteArray = QByteArray::fromBase64(base64Data.toUtf8());QImage image;image.loadFromData(byteArray);if (!image.isNull()) {// 水平居中对齐imagePreviewLabel->setAlignment(Qt::AlignHCenter);// 缩放图片到 200x200QPixmap pixmap = QPixmap::fromImage(image.scaled(200, 200, Qt::KeepAspectRatio));imagePreviewLabel->setPixmap(pixmap);} else {QMessageBox::critical(this, "错误", "无法加载图片");}}private:QPushButton *selectImageButton;QTextEdit *imagePathTextEdit;QPushButton *convertToBase64Button;QTextEdit *base64OutputTextEdit;QPushButton *convertToImagePreviewButton;QLabel *imagePreviewLabel;QString selectedImagePath;
};class Base64Converter : public QWidget {
Q_OBJECT
public:explicit Base64Converter(QWidget *parent = nullptr) : QWidget(parent) {auto *layout = new QVBoxLayout(this);inputTextEdit = new QTextEdit(this);layout->addWidget(inputTextEdit);encryptButton = new QPushButton("加密", this);connect(encryptButton, &QPushButton::clicked, this, &Base64Converter::encryptText);layout->addWidget(encryptButton);decryptButton = new QPushButton("解密", this);connect(decryptButton, &QPushButton::clicked, this, &Base64Converter::decryptText);layout->addWidget(decryptButton);outputTextEdit = new QTextEdit(this);outputTextEdit->setReadOnly(true);layout->addWidget(outputTextEdit);setLayout(layout);}private slots:void encryptText() {QString inputText = inputTextEdit->toPlainText().toUtf8();QByteArray byteArray = inputText.toUtf8().toBase64();outputTextEdit->setText(byteArray);}void decryptText() {QString inputText = inputTextEdit->toPlainText();QByteArray byteArray = QByteArray::fromBase64(inputText.toUtf8());outputTextEdit->setText(byteArray);}private:QTextEdit *inputTextEdit;QTextEdit *outputTextEdit;QPushButton *encryptButton;QPushButton *decryptButton;
};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, QOverload<int>::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);auto *base64ConverterButton = new QPushButton("显示Base64加解密功能");base64ConverterButton->setObjectName("base64ConverterButton");connect(base64ConverterButton, &QPushButton::clicked, this, &MyMainWindow::toggleBase64Converter);base64Converter = new Base64Converter(this);base64Converter->hide();layout->addWidget(base64Converter);layout->addWidget(base64ConverterButton);auto *base64ImageConverterButton = new QPushButton("显示Base64图片预览功能");base64ImageConverterButton->setObjectName("base64ImageConverterButton");connect(base64ImageConverterButton, &QPushButton::clicked, this, &MyMainWindow::toggleBase64ImageConverter);base64ImageConverter = new Base64ImageConverter(this);base64ImageConverter->hide();layout->addWidget(base64ImageConverter);layout->addWidget(base64ImageConverterButton);auto *colorConverterButton = new QPushButton("显示色值提取转换功能");colorConverterButton->setObjectName("colorConverterButton");connect(colorConverterButton, &QPushButton::clicked, this, &MyMainWindow::toggleColorConverter);colorConverter = new ColorConverter(this);colorConverter->hide();layout->addWidget(colorConverter);layout->addWidget(colorConverterButton);setLayout(layout);}private slots:void toggleClipboardManager() {auto *curButton = findChild<QPushButton *>("clipboardButton");if (clipboardManager->isHidden()) {if (curButton) {curButton->setText("隐藏管理粘贴板记录");}clipboardManager->show();} else {if (curButton) {curButton->setText("显示管理粘贴板记录");}clipboardManager->hide();}}void toggleJsonFormatter() {auto *curButton = findChild<QPushButton *>("jsonFormatButton");if (jsonFormatter->isHidden()) {if (curButton) {curButton->setText("隐藏格式化 JSON");}jsonFormatter->show();} else {if (curButton) {curButton->setText("显示格式化 JSON");}jsonFormatter->hide();}}void toggleDateTimeTimestampConverter() {auto *curButton = findChild<QPushButton *>("timestampConverterButton");if (timestampConverter->isHidden()) {if (curButton) {curButton->setText("隐藏时间戳转换");}timestampConverter->show();} else {if (curButton) {curButton->setText("显示时间戳转换");}timestampConverter->hide();}}void toggleNumberBaseConverter() {auto *curButton = findChild<QPushButton *>("numberBaseConverterButton");if (numberBaseConverter->isHidden()) {if (curButton) {curButton->setText("隐藏进制转换器");}numberBaseConverter->show();} else {if (curButton) {curButton->setText("显示进制转换器");}numberBaseConverter->hide();}}void toggleXmlFormatter() {auto *curButton = findChild<QPushButton *>("xmlFormatterButton");if (xmlFormatter->isHidden()) {if (curButton) {curButton->setText("隐藏XML格式化");}xmlFormatter->show();} else {if (curButton) {curButton->setText("显示XML格式化");}xmlFormatter->hide();}}void toggleBase64Converter() {auto *curButton = findChild<QPushButton *>("base64ConverterButton");if (base64Converter->isHidden()) {if (curButton) {curButton->setText("隐藏Base64加解密功能");}base64Converter->show();} else {if (curButton) {curButton->setText("显示Base64加解密功能");}base64Converter->hide();}}void toggleBase64ImageConverter() {auto *curButton = findChild<QPushButton *>("base64ImageConverterButton");if (base64ImageConverter->isHidden()) {if (curButton) {curButton->setText("隐藏Base64图片预览功能");}base64ImageConverter->show();} else {if (curButton) {curButton->setText("显示Base64图片预览功能");}base64ImageConverter->hide();}}void toggleColorConverter() {auto *curButton = findChild<QPushButton *>("colorConverterButton");if (colorConverter->isHidden()) {if (curButton) {curButton->setText("隐藏色值提取转换功能");}colorConverter->show();} else {if (curButton) {curButton->setText("显示色值提取转换功能");}colorConverter->hide();}}private:ClipboardManager *clipboardManager;JsonFormatter *jsonFormatter;DateTimeTimestampConverter *timestampConverter;NumberBaseConverter *numberBaseConverter;XmlFormatter *xmlFormatter;Base64Converter *base64Converter;Base64ImageConverter *base64ImageConverter;ColorConverter *colorConverter;
};int main(int argc, char *argv[]) {QApplication a(argc, argv);MyMainWindow mainWindow;mainWindow.show();return QApplication::exec();
}#include "main.moc"

想要了解这个小工具是如何发展到现在这个地步的话,就看看往期文章吧~,记得要多跑一跑代码。如果大家有什么想要的功能或者想问的问题的话,就在评论区留言吧。Thanks♪(・ω・)ノ

往期文章一览

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实现一个工具箱(增加一个进制转换器功能)- 示例代码拆分讲解

C++学习之路(十二)C++ 用Qt5实现一个工具箱(增加一个XML文本格式化功能)- 示例代码拆分讲解

C++学习之路(十三)C++ 用Qt5实现一个工具箱(增加一个Base64加解密功能)- 示例代码拆分讲解

C++学习之路(十四)C++ 用Qt5实现一个工具箱(增加一个Base64图片编码预览功能)- 示例代码拆分讲解


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

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

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

相关文章

深入解析SpringBoot的请求响应机制

SpringBootWeb请求响应 前言1. 请求1.1 Postman介绍 1.2 简单参数1.2.1 原始方式1.2.2 SpringBoot方式1.2.3 参数名不一致 1.3 实体参数1.3.1 简单实体对象1.3.2 复杂实体对象 1.4 数组集合参数1.4.1 数组1.4.2 集合 1.5 日期参数1.6 JSON参数1.7 路径参数 2. 响应2.1 Response…

电子学会C/C++编程等级考试2021年06月(四级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:数字三角形问题 (图1) 图1给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。 注意:路径上的每一步只能从一个数走到下一层上和它…

【微服务 SpringCloudAlibaba】实用篇 · Gateway服务网关

微服务&#xff08;8&#xff09; 文章目录 微服务&#xff08;8&#xff09;1. 为什么需要网关2. gateway快速入门1&#xff09;创建gateway服务&#xff0c;引入依赖2&#xff09;编写启动类3&#xff09;编写基础配置和路由规则4&#xff09;重启测试5&#xff09;网关路由的…

python之logo编程

Logo标志是一种视觉符号&#xff0c;代表着一个品牌、企业或组织的形象。它通常采用图形、字母或字形来代表一个公司或品牌&#xff0c;起到对徽标拥有公司的识别和推广的作用。Logo的设计需要考虑多种因素&#xff0c;例如颜色搭配、字体选择和构图等&#xff0c;以创造出独特…

java餐饮刀削面快餐店点餐服务系统springboot+jsp

网上点餐省去了客户很多不必要的时间和麻烦&#xff0c;给商家带来更多利益。同时&#xff0c;网上点餐可以辅助餐饮企业营销。传统的点餐是需要配备一个专业的服务员负责菜品介绍并记录顾客点单&#xff0c;确认后上交至后台厨房&#xff0c;厨房根据菜品种类安排做菜顺序最终…

11.28 C++作业

提示并输入一个字符串&#xff0c;统计该字符中大写、小写字母个数、数字个数、空格个数以及其他字符个数 要求使用C风格字符串完成 #include <iostream>using namespace std;int main() {string str;cout << "请输入一个字符串&#xff1a;" <<…

Hertz 整合swagger

文章目录 Swagger安装使用用法项目demoSwagger注释用法通用API信息 swag命令行参数swagger路由配置 Swagger 安装 go get 安装可执行文件需要配合 GOPATH 模式工作。 go get github.com/swaggo/swag/cmd/swag 因为从 Go 1.17 开始&#xff0c;在 go mod 模式下通过 go get 下…

Go 语言中 sync 包的近距离观察

让我们来看看负责提供同步原语的 Go 包&#xff1a;sync。 sync.Mutex sync.Mutex 可能是 sync 包中被广泛使用的原语。它允许对共享资源进行互斥操作&#xff08;即不允许同时访问&#xff09;&#xff1a; mutex : &sync.Mutex{}mutex.Lock() // Update shared variab…

Jinja2使用Layui报 “d is not defined“

问题出现场景在使用Jinja2渲染Layui的表格时候&#xff0c;要做自定义templte的传入 Jinja2这块本来就是支持 {{ }} 插值的模板语言&#xff0c;所以这块的第一种渲染方式会冲突 所以只能用函数返回代码块进行填充&#xff0c;不能使用插值&#xff0c;只能拼接字符串 templt…

Gradle windows下配置

1.Gradle下载 打开官网下载界面&#xff1a;https://gradle.org/releases/ 如果你使用的SpringBoot项目&#xff0c;建议使用6.8及以上的版本 2.下载后放到目录下 3.配置环境变量 配置gradle_home 配置Path 4.配置成功 5.配置国内源 新建一个init.gradle文件&#xff0c;配…

MySQL- CRUD-单表查询

一、INSERT 添加 公式 INSERT INTO table_name [(column [, column...])] VALUES (value [, value...]); 示例&#xff1a; CREATE TABLE goods (id INT ,good_name VARCHAR(10),price DOUBLE ); #添加数据 INSERT INTO goods (id,good_name,price ) VALUES (20,华为手机,…

虚假IP地址攻击的溯源方法

随着网络技术的迅速发展&#xff0c;网络攻击行为也日益猖獗。其中&#xff0c;虚假IP地址攻击是一种较为常见的网络攻击方式&#xff0c;它利用虚假的IP地址&#xff0c;通过互联网对目标进行攻击和入侵。这种攻击方式不仅难以追踪&#xff0c;而且往往会给企业和个人带来巨大…

股票要怎么买入卖出?

股票账户终于开好了&#xff01;恭喜你马上就可以开启刺激的炒股之旅了&#xff01;不过第一次买股票的你是不是还不知道怎么个买法呢&#xff1f;别担心~贴心的汇小鲸带着教程来了&#xff0c;咱们一起看看吧&#xff01; 首先一点&#xff0c;大家得知道&#xff1a;开好户还…

JavaFramework JDK Version Test

测试JDK8 JDK17编译包 当前环境JDK8 CASE 1&#xff1a; /*** * author ZengWenFeng* email 117791303QQ.com* mobile 13805029595* date 2023-08-07*/ package zwf;import a.T; import ce.pub.util.GUID;/*** 测试高版本JDK编译JAR&#xff0c;低版本错误** author ZengWenF…

震坤行:数字驱动食品农副行业采购的新兴趋势与实践

震坤行&#xff1a;数字驱动食品农副行业采购的新兴趋势与实践 近年来消费者对于营养价值和健康的追求日益凸显&#xff0c;促使各类有机食品、低糖低脂食品、素食等健康食品受到热烈追捧。同时&#xff0c;以往单一的产品也被各家企业“卷”出了个性化&#xff0c;光是卖水&a…

技术经济与企业管理 救命稻草

明天要考试了&#xff0c;今天开始预习&#xff01; 此课也叫【化工技术经济】、【工程经济学】 目录 第二章 企业战略分析市场预测方法一元线性回归方法简单移动平均法 第三章 资金的时间价值&#xff08;考&#xff09;资金时间价值的衡量利率现金流量图资金等值计算&#x…

四、设置主机名和域名映射

目录 1、配置每台虚拟机主机名 2、配置每台虚拟机域名映射 1、配置每台虚拟机主机名

windows ssh时出现Bad local forwarding specification的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

掌握HarmonyOS框架的ArkTs如何管理和共享状态数据

ARKTS&#xff08;Ark TypeScript&#xff09;是HarmonyOS应用框架的一部分&#xff0c;提供了一种灵活而强大的状态管理机制。在ARKTS中&#xff0c;AppStorage和LocalStorage是两个关键的概念&#xff0c;它们分别用于应用级和页面级的状态共享。通过深入了解这两个特性&…

2023年建筑轮廓高度数据技术服务

在之前的文章【数据分享】全国62个城市建筑轮廓数据带层数&#xff08;2018年&#xff09;和【数据分享】全国77个城市建筑轮廓数据带高度&#xff08;2019年&#xff09;里我们分别分享了2018年和2019年2020年2021年2022年的建筑轮廓数据&#xff0c;数据年份也有些老了&#…