C++学习之路(十八)C++ 用Qt5实现一个工具箱(点击按钮以新窗口打开功能面板)- 示例代码拆分讲解

上篇文章,我们用 Qt5 实现了在小工具箱中添加了《增加托盘图标并且增加显示和退出菜单》功能。今天我们把按钮打开功能的方式改一改,让点击按钮以新窗口打开功能面板。下面我们就来看看如何来规划开发这样的小功能并且添加到我们的工具箱中吧。

老规矩,先上图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

需求功能概述:

当用户点击主窗口的按钮时,需要打开一个新的窗口来显示特定功能的面板。这个新窗口应该包含用户所需功能的相关控件和布局。主要需求包括:

  1. 按钮触发:点击主窗口上的按钮触发事件,以在新窗口中显示对应的功能面板。
  2. 新窗口显示:打开新窗口时,应该显示相关的功能面板及其布局,可能包括输入框、按钮等控件。
  3. 功能面板:新窗口需要根据点击的按钮来显示相应的功能面板,这些面板可能涉及不同的逻辑和交互元素。
  4. 事件捕获:在新窗口中可能需要捕获和处理键盘事件、鼠标事件或其他用户交互事件,以响应用户的操作。

在实现过程中,需要创建一个新的窗口(例如使用 QDialogQMainWindow)并设置相应的布局和控件,以便在新窗口中显示用户所需的功能面板。此外,需要确保在新窗口中的事件处理函数中捕获并处理相应的事件,以提供所需的功能和交互体验。


核心实现代码:

class ClipboardManager : public QWidget {
Q_OBJECT
public:explicit ClipboardManager(QWidget *parent = nullptr) : QWidget(parent) {auto *newWindow = new QDialog(this);newWindow->setWindowTitle("粘贴板记录");// ...newWindow->setLayout(layout);newWindow->exec();}private slots:// ...private:// ...
};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::showClipboardManager);layout->addWidget(clipboardButton);setLayout(layout);}protected:// ...
public slots:void showClipboardManager() {new ClipboardManager(this);}// ...
};

核心代码逻辑讲解

这次变更主要包括两个类的修改:MyMainWindowClipboardManager

MyMainWindow 类:
  • 构造函数变更:主窗口中修改了按钮名字(举例 “粘贴板记录” 按钮)。
  • 槽函数变更:更改了以前的 toggle 函数名为 showXxxx 槽函数,当点击“粘贴板记录”按钮时,showClipboardManager 槽函数会创建一个新的 ClipboardManager 对象,从而打开一个新的对话框来显示粘贴板记录。
ClipboardManager 类:
  • 构造函数变更:在构造函数中创建了一个新的对话框(QDialog),用于显示粘贴板记录。
  • 对话框显示:调用 exec() 或者 show() 函数显示对话框,并在其中展示粘贴板记录(在 // ... 部分的代码)。

这次变更主要实现了点击按钮时打开一个新的对话框来展示功能。按钮点击触发了新窗口的生成和显示。


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

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QMessageBox>
#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 <QThread>
#include <QMouseEvent>
#include <QTimer>
#include <QSystemTrayIcon>
#include <QMenu>
#include <QDebug>#define myApp (dynamic_cast<QApplication *>(QCoreApplication::instance()))class ClickableLabel : public QLabel {
Q_OBJECTpublic:explicit ClickableLabel(QWidget *parent = nullptr) : QLabel(parent) {}signals:void clicked();protected:void mousePressEvent(QMouseEvent *event) override {if (event->button() == Qt::LeftButton) {emit clicked();}}
};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 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 ClickableLabel(this);screenColorOutput->setFixedSize(200, 90);screenColorOutput->setAlignment(Qt::AlignCenter);screenColorOutput->setStyleSheet("border: 1px solid #ddd");// 这里是触发点击事件后的复制到剪切板的函数调用connect(screenColorOutput, &ClickableLabel::clicked, this, &ColorConverter::copyColorToClipboard);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);}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("#%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 copyColorToClipboard() {// 从screenColorOutput获取颜色信息QString colorText = screenColorOutput->text();// 复制颜色值到剪切板QApplication::clipboard()->setText(colorText);// 弹出提示框显示复制的颜色值QMessageBox::information(this, "颜色已复制", QString("已复制颜色:") + colorText);}public:// 停止捕获颜色的槽函数void stopColorCapture() {colorTimer->stop();extractColorButton->setText("开始提取屏幕颜色");}
private:QLineEdit *colorInput;QPushButton *convertButton;QTextEdit *convertedColorOutput;QPushButton *extractColorButton;ClickableLabel *screenColorOutput;QLabel *screenColorBlock;QTimer *colorTimer;
};class Base64ImageConverter : public QWidget {
Q_OBJECT
public:explicit Base64ImageConverter(QWidget *parent = nullptr) : QWidget(parent) {auto *newWindow = new QDialog(this);newWindow->setWindowTitle("Base64图片预览");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);newWindow->setLayout(layout);newWindow->exec();}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 *newWindow = new QDialog(this);newWindow->setWindowTitle("Base64加解密");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);newWindow->setLayout(layout);newWindow->exec();}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 *newWindow = new QDialog(this);newWindow->setWindowTitle("XML格式化");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);newWindow->setLayout(layout);newWindow->exec();}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 *newWindow = new QDialog(this);newWindow->setWindowTitle("进制转换");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(); // 初始转换newWindow->setLayout(layout);newWindow->exec();}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 DateTimeTimestampConverter : public QWidget {
Q_OBJECT
public:explicit DateTimeTimestampConverter(QWidget *parent = nullptr) : QWidget(parent) {auto *newWindow = new QDialog(this);newWindow->setWindowTitle("时间戳转换");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);newWindow->setLayout(layout);newWindow->exec();}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 *newWindow = new QDialog(this);newWindow->setWindowTitle("JSON格式化");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);newWindow->setLayout(layout);newWindow->exec();}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 *newWindow = new QDialog(this);newWindow->setWindowTitle("粘贴板记录");// 创建布局并将组件添加到布局中auto *layout = new QVBoxLayout(newWindow);listWidget = new QListWidget(newWindow);updateList(); // 初始更新列表auto *clearButton = new QPushButton("清空记录", newWindow);connect(clearButton, &QPushButton::clicked, this, &ClipboardManager::clearClipboard);layout->addWidget(listWidget);layout->addWidget(clearButton);connect(myApp->clipboard(), &QClipboard::dataChanged, this, &ClipboardManager::updateList);newWindow->setLayout(layout);newWindow->exec();}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::showClipboardManager);layout->addWidget(clipboardButton);auto *jsonFormatButton = new QPushButton("JSON格式化");jsonFormatButton->setObjectName("jsonFormatButton");connect(jsonFormatButton, &QPushButton::clicked, this, &MyMainWindow::showJsonFormatter);layout->addWidget(jsonFormatButton);auto *timestampConverterButton = new QPushButton("时间戳转换");timestampConverterButton->setObjectName("timestampConverterButton");connect(timestampConverterButton, &QPushButton::clicked, this, &MyMainWindow::showDateTimeTimestampConverter);layout->addWidget(timestampConverterButton);auto *numberBaseConverterButton = new QPushButton("进制转换");numberBaseConverterButton->setObjectName("numberBaseConverterButton");connect(numberBaseConverterButton, &QPushButton::clicked, this, &MyMainWindow::showNumberBaseConverter);layout->addWidget(numberBaseConverterButton);auto *xmlFormatterButton = new QPushButton("XML格式化");xmlFormatterButton->setObjectName("xmlFormatterButton");connect(xmlFormatterButton, &QPushButton::clicked, this, &MyMainWindow::showXmlFormatter);layout->addWidget(xmlFormatterButton);auto *base64ConverterButton = new QPushButton("Base64加解密");base64ConverterButton->setObjectName("base64ConverterButton");connect(base64ConverterButton, &QPushButton::clicked, this, &MyMainWindow::showBase64Converter);layout->addWidget(base64ConverterButton);auto *base64ImageConverterButton = new QPushButton("Base64图片预览");base64ImageConverterButton->setObjectName("base64ImageConverterButton");connect(base64ImageConverterButton, &QPushButton::clicked, this, &MyMainWindow::showBase64ImageConverter);layout->addWidget(base64ImageConverterButton);auto *colorConverterButton = new QPushButton("色值提取转换");colorConverterButton->setObjectName("colorConverterButton");connect(colorConverterButton, &QPushButton::clicked, this, &MyMainWindow::showColorConverter);colorConverter = new ColorConverter(this);colorConverter->hide();layout->addWidget(colorConverter);layout->addWidget(colorConverterButton);setLayout(layout);}protected:ColorConverter *colorConverter{};// 重写关闭事件处理函数void closeEvent(QCloseEvent *event) override {if (this->isVisible()) {// 隐藏主窗口,而不是退出程序this->hide();event->ignore(); // 忽略关闭事件,防止程序退出}}void keyPressEvent(QKeyEvent *event) override {qDebug() << event->modifiers();if (event->modifiers() == Qt::ControlModifier && event->key() == Qt::Key_C) {colorConverter->stopColorCapture();// 在这里执行按下 Control + C 键的操作qDebug() << "Control + C pressed";} else {// 如果有其他键盘事件,交给基类处理QWidget::keyPressEvent(event);}}
public slots:void showClipboardManager() {new ClipboardManager(this);}void showJsonFormatter() {new JsonFormatter(this);}void showDateTimeTimestampConverter() {new DateTimeTimestampConverter(this);}void showNumberBaseConverter() {new NumberBaseConverter(this);}void showXmlFormatter() {new XmlFormatter(this);}void showBase64Converter() {new Base64Converter(this);}void showBase64ImageConverter() {new Base64ImageConverter(this);}void showColorConverter() {auto *curButton = findChild<QPushButton *>("colorConverterButton");if (colorConverter->isHidden()) {if (curButton) {curButton->setText("隐藏色值提取转换功能");}colorConverter->show();} else {if (curButton) {curButton->setText("显示色值提取转换功能");}colorConverter->hide();}}void showPanel() {this->show(); // 显示主窗口this->raise(); // 将窗口置于其他窗口上方}
};int main(int argc, char *argv[]) {QApplication a(argc, argv);MyMainWindow mainWindow;// 创建托盘图标auto* trayIcon = new QSystemTrayIcon(QIcon(":/res/icon/logo.png"), &mainWindow);trayIcon->setToolTip("天河工具箱");// 创建托盘菜单auto* trayMenu = new QMenu(&mainWindow);auto* showPanelAction = new QAction("显示面板", &mainWindow);QObject::connect(showPanelAction, &QAction::triggered, &mainWindow, &MyMainWindow::showPanel);trayMenu->addAction(showPanelAction);auto* quitAction = new QAction("退出", &mainWindow);QObject::connect(quitAction, &QAction::triggered, &a, &QApplication::quit);trayMenu->addAction(quitAction);trayIcon->setContextMenu(trayMenu);trayIcon->show();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图片编码预览功能)- 示例代码拆分讲解

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

C++学习之路(十六)C++ 用Qt5实现一个工具箱(为屏幕颜色提取功能增加一个点击复制的功能)- 示例代码拆分讲解

C++学习之路(十七)C++ 用Qt5实现一个工具箱(增加托盘图标并且增加显示和退出菜单)- 示例代码拆分讲解


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

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

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

相关文章

基于yolov8-道路裂缝检测

1 介绍 本文主要是搜集数据&#xff0c;从网上kaggle等网站找了2000多张图片&#xff0c;然后使用yolov8模型进行训练&#xff0c;最后只展示训练过程中的图片&#xff0c;如果有需要&#xff0c;可以联系&#xff1a;https://docs.qq.com/doc/DWEtRempVZ1NSZHdQ。

Hadoop实验putty文件

&#x1f525;博客主页&#xff1a; A_SHOWY&#x1f3a5;系列专栏&#xff1a;力扣刷题总结录 数据结构 云计算 数字图像处理 很多朋友反馈做hadoop实验中的putty找不到Connection-SSH-Auth路径下找不到Private key for authentication私有密钥&#xff0c;无法将转…

jenkins-cicd基础操作

1.先决条件 1.首先我个人势在k8s集群中创建的jenkins,部署方法搭建 k8s部署jenkins-CSDN博客 2.安装指定插件. 1.Gitlab plugin 用于调用gitlab-api的插件 2.Kubernetes plugin jenkins与k8s进行交互的插件,可以用来自动化的构建和部署 3.Build Authorizatio…

五金仓库ERP有哪些牌子?五金仓库ERP包含哪些功能

不同的五金企业有差异化的业务类型和管理着重点&#xff0c;而五金原材料和产成品种类繁多&#xff0c;涉及的计量单位多、出入库操作繁琐、基础资料信息管理复杂&#xff0c;如何确保有序进行每一项物品的收发工作&#xff0c;普遍存在于五金行业。 另一方面&#xff0c;物料…

免费好用的5个AI写作工具,如何更好的使用AI写作工具

人工智能&#xff08;AI&#xff09;作为当今科技领域的热门话题&#xff0c;正在以惊人的速度改变我们生活的方方面面。从智能助手到自动驾驶汽车&#xff0c;AI的应用已经渗透到我们日常的方方面面。 1. 什么是AI人工智能&#xff1f; 什么是AI人工智能&#xff1f;简而言之…

3DMM模型

目录 BFMBFM_200901_MorphableModel.matexp_pca.bintopology_info.npyexp_info.npy BFM BFM_2009 01_MorphableModel.mat from scipy.io import loadmat original_BFM loadmat("01_MorphableModel.mat") # dict_keys: [__header__, __version__, __globals__, # …

【滑动窗口】LeetCode2953:统计完全子字符串

作者推荐 [二分查找]LeetCode2040:两个有序数组的第 K 小乘积 本题其它解法 【离散差分】LeetCode2953:统计完全子字符串 题目 给你一个字符串 word 和一个整数 k 。 如果 word 的一个子字符串 s 满足以下条件&#xff0c;我们称它是 完全字符串&#xff1a; s 中每个字符…

【计算机网络笔记】物理层——物理介质

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

AI Agent 结构与分类

一、什么是AI agent 在人工智能中&#xff0c;智能代理AI Agent是以智能方式行事的代理&#xff1b;它感知环境&#xff0c;自主采取行动以实现目标&#xff0c;并可以通过学习或获取知识来提高其性能。人其实就是一种复杂代理。 为了理解智能代理的结构&#xff0c;我们应该熟…

录视频人不在电脑旁,怎么设置定时关机

如果你平常工作比较忙&#xff0c;或者要录制的视频/音频文件需要很长时间&#xff0c;最好选择预约录制&#xff0c;这样可使录屏软件自动开始和停止录制&#xff0c;并且定时关机。此外&#xff0c;你还可以设置保存录制文件、关闭录屏软件。是不是听起来很感兴趣&#xff1f…

鸿蒙系统扫盲(四):鸿蒙使用的是微内核?

我们常说&#xff0c;看一个系统是不是自研&#xff0c;就看它的内核&#xff0c;常见的内核分为&#xff1a;宏内核和微内核&#xff0c;当然还有两者结合体&#xff0c;他们到底有什么区别&#xff1f; 1.白话宏内核和微内核 有一天&#xff0c;你结婚了&#xff0c;你和你…

使用Notepad++编辑器,安装AnalysePlugin搜索插件

概述 是一款非常有特色的编辑器&#xff0c;Notepad是开源软件&#xff0c;Notepad中文版可以免费使用。 操作步骤&#xff1a; 1、在工具栏 ->“插件”选项。 2、勾选AnalysePlugin选项&#xff0c;点击右上角“安装”即可。 3、 确认安装插件 4、下载插件 5、插件已安装…

【算法专题】前缀和

前缀和 前缀和1. 前缀和【模板】2. 二维前缀和【模板】3. 寻找数组的中心下标4. 除自身以外数组的乘积5. 和为K的子数组6. 和可被K整除的子数组7. 连续数组8. 矩阵区域和 前缀和 1. 前缀和【模板】 题目链接 -> Nowcoder -DP34.前缀和【模板】 Nowcoder -DP34.前缀和【模…

15、pytest的fixture调用fixture

官方实例 # content of test_append.py import pytest# Arrange pytest.fixture def first_entry():return "a"# Arrange pytest.fixture def order(first_entry):return [first_entry]def test_string(order):# Actorder.append("b")# Assertassert orde…

failed to install plugin grafana 插件安装失败

升级时忽略plugins 权限问题&#xff0c;导致安装插件失败&#xff01;调整权限即可

论文解读--PointPillars- Fast Encoders for Object Detection from Point Clouds

PointPillars--点云目标检测的快速编码器 摘要 点云中的物体检测是许多机器人应用(如自动驾驶)的重要方面。在本文中&#xff0c;我们考虑将点云编码为适合下游检测流程的格式的问题。最近的文献提出了两种编码器;固定编码器往往很快&#xff0c;但牺牲了准确性&#xff0c;而…

【报名】2023产业区块链生态日暨 FISCO BCOS 开源六周年生态大会

作为2023深圳国际金融科技节系列活动之一&#xff0c;由深圳市地方金融监督管理局指导&#xff0c;微众银行、金链盟主办的“2023产业区块链生态日暨FISCO BCOS开源六周年生态大会”将于12月15日下午14:00在深圳举办。 今年的盛会将进一步升级&#xff0c;以“FISCO BCOS和TA的…

C# - Opencv应用(3) 之矩阵Mat使用[图像截取粘贴、ROI操作、位运算、数学计算]

C# - Opencv应用&#xff08;3&#xff09; 之矩阵Mat使用[图像截取粘贴、ROI操作、位运算、数学计算] 图像读取&#xff0c;大小、截取、位运算图像ROI操作&#xff1a;粘贴赋值、滤波图像数学计算部分结果如下&#xff1a; 1.图像读取&#xff0c;大小、截取、位运算 //图…

nodejs微信小程序+python+PHP天天网站书城管理系统的设计与实现-计算机毕业设计推荐

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

vs 安装 qt qt扩展 改迅雷下载qt

Qt5.14.2安装教程和VS2019中的qt环境配置-CSDN博客 1 安装qt 社区版 免费 Download Qt OSS: Get Qt Online Installer 2 vs安装 qt vs tools 3 vs添加 qt添加 bin/cmake.exe 路径 3.1 扩展 -> qt versions 3.2 4 新版要源码安装 需要自己安装 安装独立安装的旧版 官网…