展开菜单
首页 精品内容 本月促销 装机必备 Windows PDF教程 macOS软件 IOS软件 Android AI 专题
全部分类

当前位置:

首页 > 编程开发 > 基于Qt的实用二维码生成解决方案

基于Qt的实用二维码生成解决方案

纯C++且无任何依赖的nayukiqrcode库最适合Qt项目集成二维码功能,通过QRCodeWidget类可方便实现生成、保存、添加Logo及自定义样式设置。该库轻量高效,无需额外配置。相比之下,QZXing和libqrencode因体积较大或需编译而推荐度较低。

本文目录

    在Qt项目中集成二维码生成功能,通常有几种主流选择。下面把各方案的优劣势摆出来,再结合集成难度和实际使用场景,给出一份靠谱的推荐。

    一、解决方案架构

    1.1 技术选型比较

    方案优点缺点推荐度
    qrcode (nayuki)纯C++, 轻量, 无依赖功能基础★★★★★
    QZXing功能强大, 支持多种格式体积大, 依赖多★★★★
    libqrencode性能好, 广泛使用需要额外编译★★★★
    ZXing-C++Google出品, 功能全编译复杂★★★

    推荐方案:qrcode (nayuki) - 最适合Qt集成

    基于Qt的实用二维码生成解决方案

    二、核心实现方案

    2.1 方案一:使用 qrcode (nayuki) - 推荐

    要说最轻量、最容易集成的方案,非它莫属。纯C++实现,没有任何外部依赖,直接扔进项目就能用。

    下载qrcode库

    # 下载qrcode库
    git clone https://github.com/nayuki/QR-Code-generator.git

    Qt项目集成

    文件结构:

    QRCodeDemo/

    ├── main.cpp

    ├── QRCodeWidget.h

    ├── QRCodeWidget.cpp

    ├── qrcode/

    │ ├── BitBuffer.hpp

    │ ├── QrCode.hpp

    │ ├── QrSegment.hpp

    │ └── README.md

    └── QRCodeDemo.pro

    QRCodeWidget.h:

    #ifndef QRCODEWIDGET_H
    #define QRCODEWIDGET_H
    #include 
    #include 
    #include 
    #include 
    #include 
    class QRCodeWidget : public QWidget
    {
        Q_OBJECT
    public:
        explicit QRCodeWidget(QWidget *parent = nullptr);
        // 生成二维码
        bool generateQRCode(const QString& text, 
                           int version = 5,  // 二维码版本(1-40)
                           int eccLevel = 1, // 纠错等级(0-3)
                           int border = 4);  // 边距
        // 获取二维码图片
        QImage getQRCodeImage() const { return m_qrCodeImage; }
        // 保存二维码图片
        bool sa veToFile(const QString& filename, 
                       int scale = 4,  // 缩放倍数
                       const QString& format = "PNG");
        // 设置样式
        void setForegroundColor(const QColor& color) { m_foregroundColor = color; }
        void setBackgroundColor(const QColor& color) { m_backgroundColor = color; }
        void setDrawStyle(bool rounded = false, bool useGradient = false);
        // 添加Logo
        bool addLogo(const QImage& logo, int logoSizePercentage = 20);
        // 二维码信息
        int getVersion() const { return m_version; }
        int getEccLevel() const { return m_eccLevel; }
        QString getEccLevelName() const;
        int getSize() const { return m_qrSize; }
    protected:
        void paintEvent(QPaintEvent *event) override;
    signals:
        void qrCodeGenerated(bool success, const QString& error = QString());
    private:
        // 绘制二维码
        void drawQRCode(QPainter& painter, int x, int y, int size);
        // 绘制Logo
        void drawLogo(QPainter& painter, int x, int y, int size);
        // 计算版本容量
        static int getMaxCapacity(int version, int eccLevel);
    private:
        QImage m_qrCodeImage;
        QImage m_logoImage;
        QColor m_foregroundColor = Qt::black;
        QColor m_backgroundColor = Qt::white;
        int m_version = 5;
        int m_eccLevel = 1;  // 1 = LOW, 0 = MEDIUM, 2 = QUARTILE, 3 = HIGH
        int m_border = 4;
        int m_qrSize = 0;
        bool m_roundedModules = false;
        bool m_useGradient = false;
        std::vector m_qrData;
    };
    #endif // QRCODEWIDGET_H

    QRCodeWidget.cpp:

    #include "QRCodeWidget.h"
    #include "qrcode/QrCode.hpp"
    #include 
    #include 
    #include 
    #include 
    #include 
    
    using qrcodegen::QrCode;
    using qrcodegen::QrSegment;
    
    QRCodeWidget::QRCodeWidget(QWidget *parent) 
        : QWidget(parent) {
        setMinimumSize(200, 200);
    }
    
    bool QRCodeWidget::generateQRCode(const QString& text, int version, int eccLevel, int border) {
        if (text.isEmpty()) {
            emit qrCodeGenerated(false, "文本不能为空");
            return false;
        }
        
        if (version < 1 || version > 40) {
            emit qrCodeGenerated(false, "版本必须在1-40之间");
            return false;
        }
        
        if (eccLevel < 0 || eccLevel > 3) {
            emit qrCodeGenerated(false, "纠错等级必须在0-3之间");
            return false;
        }
        
        m_version = version;
        m_eccLevel = eccLevel;
        m_border = border;
        
        try {
            // 将QString转换为UTF-8字节
            QByteArray utf8Data = text.toUtf8();
            std::vector data(utf8Data.begin(), utf8Data.end());
            
            // 创建QR码
            QrCode::Ecc ecc = static_cast(eccLevel);
            QrCode qr = QrCode::encodeBytes(data, ecc, version, version);
            
            m_qrSize = qr.getSize();
            m_qrData.clear();
            
            // 复制二维码数据
            for (int y = 0; y < m_qrSize; y++) {
                for (int x = 0; x < m_qrSize; x++) {
                    m_qrData.push_back(qr.getModule(x, y) ? 1 : 0);
                }
            }
            
            // 创建图片
            int imgSize = m_qrSize + 2 * m_border;
            m_qrCodeImage = QImage(imgSize, imgSize, QImage::Format_ARGB32);
            m_qrCodeImage.fill(m_backgroundColor);
            
            QPainter painter(&m_qrCodeImage);
            painter.setRenderHint(QPainter::Antialiasing);
            drawQRCode(painter, m_border, m_border, m_qrSize);
            
            // 如果有Logo,绘制Logo
            if (!m_logoImage.isNull()) {
                drawLogo(painter, m_border, m_border, m_qrSize);
            }
            
            painter.end();
            
            update();  // 触发重绘
            emit qrCodeGenerated(true);
            return true;
            
        } catch (const std::exception& e) {
            qWarning() << "生成二维码失败:" << e.what();
            emit qrCodeGenerated(false, QString("生成失败: %1").arg(e.what()));
            return false;
        }
    }
    
    void QRCodeWidget::drawQRCode(QPainter& painter, int x, int y, int size) {
        int moduleSize = size / m_qrSize;
        
        painter.setPen(Qt::NoPen);
        
        if (m_useGradient) {
            QLinearGradient gradient(x, y, x + size, y + size);
            gradient.setColorAt(0, m_foregroundColor);
            gradient.setColorAt(1, m_foregroundColor.darker(150));
            painter.setBrush(gradient);
        } else {
            painter.setBrush(m_foregroundColor);
        }
        
        for (int row = 0; row < m_qrSize; row++) {
            for (int col = 0; col < m_qrSize; col++) {
                if (m_qrData[row * m_qrSize + col]) {
                    int px = x + col * moduleSize;
                    int py = y + row * moduleSize;
                    
                    if (m_roundedModules) {
                        painter.drawRoundedRect(px, py, moduleSize, moduleSize, 
                                               moduleSize / 3, moduleSize / 3);
                    } else {
                        painter.drawRect(px, py, moduleSize, moduleSize);
                    }
                }
            }
        }
    }
    
    void QRCodeWidget::drawLogo(QPainter& painter, int x, int y, int size) {
        if (m_logoImage.isNull()) return;
        
        int logoSize = size * 0.2;  // Logo大小为二维码的20%
        int centerX = x + (size - logoSize) / 2;
        int centerY = y + (size - logoSize) / 2;
        
        QPixmap logoPixmap = QPixmap::fromImage(m_logoImage)
            .scaled(logoSize, logoSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
        
        // 绘制白色背景
        painter.setBrush(Qt::white);
        painter.setPen(Qt::NoPen);
        painter.drawRoundedRect(centerX - 2, centerY - 2, 
                               logoSize + 4, logoSize + 4, 8, 8);
        
        // 绘制Logo
        painter.drawPixmap(centerX, centerY, logoPixmap);
    }
    
    bool QRCodeWidget::sa veToFile(const QString& filename, int scale, const QString& format) {
        if (m_qrCodeImage.isNull()) {
            return false;
        }
        
        QImage scaledImage = m_qrCodeImage.scaled(
            m_qrCodeImage.width() * scale,
            m_qrCodeImage.height() * scale,
            Qt::KeepAspectRatio,
            Qt::SmoothTransformation
        );
        
        return scaledImage.sa ve(filename, format.toUpper().toUtf8());
    }
    
    void QRCodeWidget::setDrawStyle(bool rounded, bool useGradient) {
        m_roundedModules = rounded;
        m_useGradient = useGradient;
        update();
    }
    
    bool QRCodeWidget::addLogo(const QImage& logo, int logoSizePercentage) {
        if (logo.isNull()) {
            m_logoImage = QImage();
            return false;
        }
        
        m_logoImage = logo;
        update();
        return true;
    }
    
    QString QRCodeWidget::getEccLevelName() const {
        switch (m_eccLevel) {
        case 0: return "LOW (7%)";
        case 1: return "MEDIUM (15%)";
        case 2: return "QUARTILE (25%)";
        case 3: return "HIGH (30%)";
        default: return "UNKNOWN";
        }
    }
    
    int QRCodeWidget::getMaxCapacity(int version, int eccLevel) {
        // 简化的容量表(数字模式)
        static const int capacityTable[4][4] = {
            {17, 32, 53, 78},     // 版本1
            {32, 61, 100, 127},   // 版本2
            {53, 101, 165, 198},  // 版本3
            {78, 127, 198, 242}   // 版本4
        };
        
        if (version >= 1 && version <= 4 && eccLevel >= 0 && eccLevel <= 3) {
            return capacityTable[version-1][eccLevel];
        }
        return 0;
    }
    
    void QRCodeWidget::paintEvent(QPaintEvent *event) {
        Q_UNUSED(event);
        
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        
        if (!m_qrCodeImage.isNull()) {
            // 居中显示
            int x = (width() - m_qrCodeImage.width()) / 2;
            int y = (height() - m_qrCodeImage.height()) / 2;
            painter.drawImage(x, y, m_qrCodeImage);
        } else {
            // 显示提示
            painter.setPen(Qt::gray);
            painter.drawText(rect(), Qt::AlignCenter, "没有二维码数据");
        }
    }
    

    main.cpp:

    #include "MainWindow.h"
    #include 
    
    int main(int argc, char *argv[]) {
        QApplication app(argc, argv);
        
        // 设置应用程序信息
        app.setApplicationName("QR Code Generator");
        app.setOrganizationName("MyCompany");
        app.setApplicationVersion("1.0.0");
        
        MainWindow window;
        window.show();
        
        return app.exec();
    }
    

    2.2 方案二:使用QZXing库

    QZXing是Qt生态里功能比较全面的二维码处理库,不光能生成,还能解码,支持多种格式。

    安装QZXing

    # 方法1:通过vcpkg
    vcpkg install qzxing
    
    # 方法2:手动编译
    git clone https://github.com/ftylitak/qzxing.git
    cd qzxing
    mkdir build && cd build
    cmake ..
    make
    make install
    

    使用QZXing生成二维码

    // QZXingGenerator.h
    #ifndef QZXINGGENERATOR_H
    #define QZXINGGENERATOR_H
    
    #include 
    #include 
    #include 
    #include 
    
    class QZXingGenerator : public QObject
    {
        Q_OBJECT
        
    public:
        explicit QZXingGenerator(QObject *parent = nullptr);
        
        // 生成二维码
        QImage generateQRCode(const QString& data, 
                             const QSize& size = QSize(200, 200),
                             const QColor& foreground = Qt::black,
                             const QColor& background = Qt::white,
                             QZXing::EncoderCorrectionLevel correction = QZXing::EncodeErrorCorrectionLevel_M);
        
        // 生成带Logo的二维码
        QImage generateQRCodeWithLogo(const QString& data, 
                                     const QImage& logo,
                                     const QSize& size = QSize(200, 200));
        
        // 批量生成
        QList batchGenerate(const QStringList& dataList, 
                                   const QSize& size = QSize(200, 200));
        
        // 保存到文件
        bool sa veQRCode(const QString& data, 
                       const QString& filename,
                       const QSize& size = QSize(200, 200));
        
    signals:
        void generationComplete(const QImage& qrCode);
        void generationError(const QString& error);
        
    private:
        QZXing m_qzxing;
    };
    #endif // QZXINGGENERATOR_H
    
    // QZXingGenerator.cpp
    #include "QZXingGenerator.h"
    #include 
    #include 
    #include 
    
    QZXingGenerator::QZXingGenerator(QObject *parent) 
        : QObject(parent) {
        // 初始化QZXing
        m_qzxing.setDecoder(QZXing::DecoderFormat_QR_CODE);
    }
    
    QImage QZXingGenerator::generateQRCode(const QString& data, 
                                          const QSize& size,
                                          const QColor& foreground,
                                          const QColor& background,
                                          QZXing::EncoderCorrectionLevel correction) {
        if (data.isEmpty()) {
            emit generationError("数据不能为空");
            return QImage();
        }
        
        try {
            // 设置编码参数
            QZXing::EncodeErrorCorrectionLevel eccLevel = correction;
            
            // 生成二维码
            QImage qrCode = m_qzxing.encodeData(data, size, foreground, background, eccLevel);
            
            if (qrCode.isNull()) {
                emit generationError("生成二维码失败");
                return QImage();
            }
            
            emit generationComplete(qrCode);
            return qrCode;
            
        } catch (const std::exception& e) {
            emit generationError(QString("生成错误: %1").arg(e.what()));
            return QImage();
        }
    }
    
    QImage QZXingGenerator::generateQRCodeWithLogo(const QString& data, 
                                                  const QImage& logo,
                                                  const QSize& size) {
        // 先生成基本二维码
        QImage qrCode = generateQRCode(data, size);
        if (qrCode.isNull() || logo.isNull()) {
            return qrCode;
        }
        
        // 在二维码中心添加Logo
        QImage result = qrCode.copy();
        QPainter painter(&result);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setRenderHint(QPainter::SmoothPixmapTransform);
        
        // 计算Logo位置和大小
        int logoSize = qMin(size.width(), size.height()) * 0.2;  // Logo大小为20%
        int x = (size.width() - logoSize) / 2;
        int y = (size.height() - logoSize) / 2;
        
        // 绘制白色背景
        painter.setBrush(Qt::white);
        painter.setPen(Qt::NoPen);
        painter.drawRoundedRect(x-2, y-2, logoSize+4, logoSize+4, 5, 5);
        
        // 绘制Logo
        QPixmap scaledLogo = QPixmap::fromImage(logo)
            .scaled(logoSize, logoSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
        painter.drawPixmap(x, y, scaledLogo);
        
        return result;
    }
    
    QList QZXingGenerator::batchGenerate(const QStringList& dataList, 
                                                const QSize& size) {
        QList result;
        
        for (const QString& data : dataList) {
            QImage qrCode = generateQRCode(data, size);
            if (!qrCode.isNull()) {
                result.append(qrCode);
            }
        }
        
        return result;
    }
    
    bool QZXingGenerator::sa veQRCode(const QString& data, 
                                    const QString& filename,
                                    const QSize& size) {
        QImage qrCode = generateQRCode(data, size);
        if (qrCode.isNull()) {
            return false;
        }
        
        return qrCode.sa ve(filename);
    }
    

    2.3 方案三:使用libqrencode

    这是一款C语言写的二维码生成库,性能相当不错,在很多开源项目里都有它的身影。

    安装libqrencode

    # Ubuntu/Debian
    sudo apt-get install libqrencode-dev
    # macOS
    brew install qrencode
    # Windows (vcpkg)
    vcpkg install qrencode

    libqrencode封装

    // LibQRencodeWrapper.h
    #ifndef LIBQRENCODEWRAPPER_H
    #define LIBQRENCODEWRAPPER_H
    
    #include 
    #include 
    #include 
    
    class LibQRencodeWrapper
    {
    public:
        enum QRCorrectionLevel {
            QR_ECLEVEL_L = 0,  // 7% 纠错
            QR_ECLEVEL_M = 1,  // 15% 纠错
            QR_ECLEVEL_Q = 2,  // 25% 纠错
            QR_ECLEVEL_H = 3   // 30% 纠错
        };
        
        struct QRCodeOptions {
            int version = 0;           // 0 = 自动选择
            QRCorrectionLevel level = QR_ECLEVEL_M;
            int margin = 4;            // 边距
            int scale = 4;             // 缩放倍数
            bool caseSensitive = true; // 大小写敏感
        };
        
        static QImage generateQRCode(const QString& text, 
                                    const QRCodeOptions& options = QRCodeOptions());
        
        static QString getLibraryVersion();
        
        static int getMaxVersion() { return 40; }
        static int getMinVersion() { return 1; }
        
    private:
        static QRcode* encodeString(const QString& text, 
                                   const QRCodeOptions& options);
    };
    #endif // LIBQRENCODEWRAPPER_H
    
    // LibQRencodeWrapper.cpp
    #include "LibQRencodeWrapper.h"
    #include 
    #include 
    
    QImage LibQRencodeWrapper::generateQRCode(const QString& text, 
                                             const QRCodeOptions& options) {
        if (text.isEmpty()) {
            return QImage();
        }
        
        QRcode* qr = encodeString(text, options);
        if (!qr) {
            qWarning() << "Failed to generate QR code";
            return QImage();
        }
        
        // 计算图片大小
        int qrSize = qr->width;
        int imageSize = (qrSize + 2 * options.margin) * options.scale;
        
        QImage image(imageSize, imageSize, QImage::Format_ARGB32);
        image.fill(Qt::white);
        
        QPainter painter(&image);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setBrush(Qt::black);
        painter.setPen(Qt::NoPen);
        
        // 绘制二维码
        for (int y = 0; y < qrSize; y++) {
            for (int x = 0; x < qrSize; x++) {
                if (qr->data[y * qrSize + x] & 1) {
                    int px = (options.margin + x) * options.scale;
                    int py = (options.margin + y) * options.scale;
                    painter.drawRect(px, py, options.scale, options.scale);
                }
            }
        }
        
        painter.end();
        QRcode_free(qr);
        
        return image;
    }
    
    QRcode* LibQRencodeWrapper::encodeString(const QString& text, 
                                            const QRCodeOptions& options) {
        QRecLevel level = static_cast(options.level);
        QRecLevel* hint = options.caseSensitive ? QR_MODE_8 : QR_MODE_KANJI;
        
        QRcode* qr = nullptr;
        
        if (options.version > 0) {
            // 指定版本
            qr = QRcode_encodeString(text.toUtf8().constData(),
                                     options.version,
                                     level,
                                     hint,
                                     1);
        } else {
            // 自动选择版本
            qr = QRcode_encodeString(text.toUtf8().constData(),
                                     0,
                                     level,
                                     hint,
                                     1);
        }
        
        return qr;
    }
    
    QString LibQRencodeWrapper::getLibraryVersion() {
        return QString("libqrencode %1").arg(qrencode_version());
    }
    

    三、功能丰富的二维码生成器

    3.1 主窗口设计

    // MainWindow.h
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include 
    #include 
    #include "QRCodeWidget.h"
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
        
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
        
    private slots:
        void onGenerateClicked();
        void onSa veClicked();
        void onClearClicked();
        void onAddLogoClicked();
        void onRemoveLogoClicked();
        void onTextChanged();
        void onStyleChanged();
        void onQRCodeGenerated(bool success, const QString& error = QString());
        void onUpdatePreview();
        
    private:
        void setupUI();
        void setupConnections();
        void updateCapacityInfo();
        void loadSettings();
        void sa veSettings();
        
    private:
        Ui::MainWindow *ui;
        QRCodeWidget *m_qrCodeWidget;
        QImage m_logoImage;
        QTimer *m_previewTimer;
    };
    #endif // MAINWINDOW_H
    
    // MainWindow.cpp
    #include "MainWindow.h"
    #include "ui_MainWindow.h"
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
        , m_qrCodeWidget(new QRCodeWidget(this))
        , m_previewTimer(new QTimer(this)) {
        
        ui->setupUI(this);
        setupUI();
        setupConnections();
        loadSettings();
        
        m_previewTimer->setSingleShot(true);
        m_previewTimer->setInterval(500);  // 500ms延迟预览
    }
    
    MainWindow::~MainWindow() {
        sa veSettings();
        delete ui;
    }
    
    void MainWindow::setupUI() {
        // 设置中心窗口
        setCentralWidget(m_qrCodeWidget);
        
        // 创建工具栏
        QToolBar *toolBar = addToolBar("Main");
        toolBar->setMovable(false);
        
        toolBar->addAction("生成", this, &MainWindow::onGenerateClicked);
        toolBar->addAction("保存", this, &MainWindow::onSa veClicked);
        toolBar->addAction("清除", this, &MainWindow::onClearClicked);
        toolBar->addSeparator();
        toolBar->addAction("添加Logo", this, &MainWindow::onAddLogoClicked);
        toolBar->addAction("移除Logo", this, &MainWindow::onRemoveLogoClicked);
        
        // 创建状态栏
        statusBar()->showMessage("就绪");
        
        // 初始化控件
        for (int i = 1; i <= 10; i++) {
            ui->comboVersion->addItem(QString("V%1").arg(i), i);
        }
        ui->comboVersion->setCurrentIndex(4);  // 默认V5
        
        ui->comboECC->addItem("LOW (7%)", 0);
        ui->comboECC->addItem("MEDIUM (15%)", 1);
        ui->comboECC->addItem("QUARTILE (25%)", 2);
        ui->comboECC->addItem("HIGH (30%)", 3);
        ui->comboECC->setCurrentIndex(1);  // 默认MEDIUM
        
        ui->spinBorder->setValue(4);
        ui->spinScale->setValue(4);
        
        updateCapacityInfo();
    }
    
    void MainWindow::setupConnections() {
        connect(ui->btnGenerate, &QPushButton::clicked, 
                this, &MainWindow::onGenerateClicked);
        connect(ui->btnSa ve, &QPushButton::clicked, 
                this, &MainWindow::onSa veClicked);
        connect(ui->btnClear, &QPushButton::clicked, 
                this, &MainWindow::onClearClicked);
        connect(ui->btnAddLogo, &QPushButton::clicked, 
                this, &MainWindow::onAddLogoClicked);
        connect(ui->btnRemoveLogo, &QPushButton::clicked, 
                this, &MainWindow::onRemoveLogoClicked);
        connect(ui->textContent, &QTextEdit::textChanged, 
                this, &MainWindow::onTextChanged);
        connect(ui->checkRounded, &QCheckBox::toggled, 
                this, &MainWindow::onStyleChanged);
        connect(ui->checkGradient, &QCheckBox::toggled, 
                this, &MainWindow::onStyleChanged);
        connect(ui->btnCopy, &QPushButton::clicked,  {
            QApplication::clipboard()->setPixmap(
                QPixmap::fromImage(m_qrCodeWidget->getQRCodeImage())
            );
            statusBar()->showMessage("二维码已复制到剪贴板", 2000);
        });
        
        connect(m_qrCodeWidget, &QRCodeWidget::qrCodeGenerated,
                this, &MainWindow::onQRCodeGenerated);
        connect(m_previewTimer, &QTimer::timeout,
                this, &MainWindow::onUpdatePreview);
    }
    
    void MainWindow::onGenerateClicked() {
        QString text = ui->textContent->toPlainText().trimmed();
        if (text.isEmpty()) {
            QMessageBox::warning(this, "警告", "请输入要编码的内容");
            return;
        }
        
        int version = ui->comboVersion->currentData().toInt();
        int eccLevel = ui->comboECC->currentData().toInt();
        int border = ui->spinBorder->value();
        
        // 检查内容长度是否超过容量限制
        int maxCapacity = m_qrCodeWidget->getMaxCapacity(version, eccLevel);
        if (text.length() > maxCapacity) {
            QMessageBox::warning(this, "警告", 
                QString("内容过长!最大容量为%1字符,当前%2字符")
                .arg(maxCapacity).arg(text.length()));
            return;
        }
        
        statusBar()->showMessage("正在生成二维码...");
        m_qrCodeWidget->generateQRCode(text, version, eccLevel, border);
    }
    
    void MainWindow::onSa veClicked() {
        if (m_qrCodeWidget->getQRCodeImage().isNull()) {
            QMessageBox::warning(this, "警告", "没有可保存的二维码");
            return;
        }
        
        QString filter = "PNG 图片 (*.png);;JPEG 图片 (*.jpg *.jpeg);;BMP 图片 (*.bmp)";
        QString filename = QFileDialog::getSa veFileName(this, "保存二维码", 
                                                       "qrcode.png", filter);
        
        if (!filename.isEmpty()) {
            int scale = ui->spinScale->value();
            QString format = QFileInfo(filename).suffix().toUpper();
            
            if (m_qrCodeWidget->sa veToFile(filename, scale, format)) {
                statusBar()->showMessage(QString("保存成功: %1").arg(filename), 3000);
            } else {
                QMessageBox::critical(this, "错误", "保存失败");
            }
        }
    }
    
    void MainWindow::onClearClicked() {
        ui->textContent->clear();
        m_qrCodeWidget->addLogo(QImage());  // 移除Logo
        statusBar()->showMessage("已清除", 2000);
    }
    
    void MainWindow::onAddLogoClicked() {
        QString filename = QFileDialog::getOpenFileName(this, "选择Logo图片", 
                                                       "", 
                                                       "图片文件 (*.png *.jpg *.jpeg *.bmp)");
        if (!filename.isEmpty()) {
            m_logoImage.load(filename);
            if (m_logoImage.isNull()) {
                QMessageBox::warning(this, "警告", "无法加载图片");
                return;
            }
            
            m_qrCodeWidget->addLogo(m_logoImage, ui->spinLogoSize->value());
            statusBar()->showMessage("Logo已添加", 2000);
        }
    }
    
    void MainWindow::onRemoveLogoClicked() {
        m_logoImage = QImage();
        m_qrCodeWidget->addLogo(QImage());  // 移除Logo
        statusBar()->showMessage("Logo已移除", 2000);
    }
    
    void MainWindow::onTextChanged() {
        // 延迟预览
        m_previewTimer->start();
        updateCapacityInfo();
    }
    
    void MainWindow::onStyleChanged() {
        bool rounded = ui->checkRounded->isChecked();
        bool gradient = ui->checkGradient->isChecked();
        m_qrCodeWidget->setDrawStyle(rounded, gradient);
    }
    
    void MainWindow::onQRCodeGenerated(bool success, const QString& error) {
        if (success) {
            QString info = QString("版本: V%1, 纠错: %2, 尺寸: %3×%3")
                .arg(m_qrCodeWidget->getVersion())
                .arg(m_qrCodeWidget->getEccLevelName())
                .arg(m_qrCodeWidget->getSize());
            statusBar()->showMessage(info);
        } else {
            QMessageBox::critical(this, "错误", error);
            statusBar()->showMessage("生成失败");
        }
    }
    
    void MainWindow::onUpdatePreview() {
        if (ui->checkAutoPreview->isChecked()) {
            onGenerateClicked();
        }
    }
    
    void MainWindow::updateCapacityInfo() {
        int version = ui->comboVersion->currentData().toInt();
        int eccLevel = ui->comboECC->currentData().toInt();
        int currentLength = ui->textContent->toPlainText().length();
        int maxCapacity = m_qrCodeWidget->getMaxCapacity(version, eccLevel);
        
        QString info = QString("长度: %1 / %2").arg(currentLength).arg(maxCapacity);
        ui->labelCapacity->setText(info);
        
        // 进度条显示
        int percent = qMin(100, (currentLength * 100) / maxCapacity);
        ui->progressCapacity->setValue(percent);
        
        // 颜色指示
        if (percent > 90) {
            ui->progressCapacity->setStyleSheet("QProgressBar::chunk { background-color: red; }");
        } else if (percent > 70) {
            ui->progressCapacity->setStyleSheet("QProgressBar::chunk { background-color: orange; }");
        } else {
            ui->progressCapacity->setStyleSheet("");
        }
    }
    
    void MainWindow::loadSettings() {
        QSettings settings;
        
        // 加载窗口位置和大小
        if (settings.contains("geometry")) {
            restoreGeometry(settings.value("geometry").toByteArray());
        }
        
        // 加载上次的内容
        QString lastContent = settings.value("lastContent").toString();
        if (!lastContent.isEmpty()) {
            ui->textContent->setPlainText(lastContent);
        }
    }
    
    void MainWindow::sa veSettings() {
        QSettings settings;
        
        // 保存窗口位置和大小
        settings.setValue("geometry", sa veGeometry());
        
        // 保存当前内容
        settings.setValue("lastContent", ui->textContent->toPlainText());
    }
    

    3.2 UI界面设计 (ui_MainWindow.h)

    // UI设计文件 (通过Qt Designer创建)
    #ifndef UI_MAINWINDOW_H
    #define UI_MAINWINDOW_H
    
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    class Ui_MainWindow {
    public:
        QWidget *centralWidget;
        QVBoxLayout *verticalLayout;
        QHBoxLayout *horizontalLayout;
        QVBoxLayout *leftLayout;
        QTextEdit *textContent;
        QHBoxLayout *buttonLayout;
        QPushButton *btnGenerate;
        QPushButton *btnSa ve;
        QPushButton *btnClear;
        QPushButton *btnCopy;
        QVBoxLayout *rightLayout;
        QGroupBox *groupSettings;
        QVBoxLayout *settingsLayout;
        QHBoxLayout *layoutVersion;
        QLabel *labelVersion;
        QComboBox *comboVersion;
        QHBoxLayout *layoutECC;
        QLabel *labelECC;
        QComboBox *comboECC;
        QHBoxLayout *layoutBorder;
        QLabel *labelBorder;
        QSpinBox *spinBorder;
        QHBoxLayout *layoutScale;
        QLabel *labelScale;
        QSpinBox *spinScale;
        QHBoxLayout *layoutLogo;
        QLabel *labelLogo;
        QSpinBox *spinLogoSize;
        QPushButton *btnAddLogo;
        QPushButton *btnRemoveLogo;
        QGroupBox *groupStyle;
        QVBoxLayout *styleLayout;
        QCheckBox *checkRounded;
        QCheckBox *checkGradient;
        QCheckBox *checkAutoPreview;
        QGroupBox *groupInfo;
        QVBoxLayout *infoLayout;
        QLabel *labelCapacity;
        QProgressBar *progressCapacity;
        
        void setupUI(QMainWindow *MainWindow) {
            if (MainWindow->objectName().isEmpty())
                MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
            MainWindow->resize(800, 600);
            
            centralWidget = new QWidget(MainWindow);
            centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
            
            verticalLayout = new QVBoxLayout(centralWidget);
            verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
            
            horizontalLayout = new QHBoxLayout();
            horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
            
            // 左侧:输入区域
            leftLayout = new QVBoxLayout();
            leftLayout->setObjectName(QString::fromUtf8("leftLayout"));
            
            textContent = new QTextEdit(centralWidget);
            textContent->setObjectName(QString::fromUtf8("textContent"));
            textContent->setPlaceholderText("请输入要编码的内容...");
            leftLayout->addWidget(textContent);
            
            buttonLayout = new QHBoxLayout();
            buttonLayout->setObjectName(QString::fromUtf8("buttonLayout"));
            
            btnGenerate = new QPushButton(centralWidget);
            btnGenerate->setObjectName(QString::fromUtf8("btnGenerate"));
            btnGenerate->setText("生成二维码");
            buttonLayout->addWidget(btnGenerate);
            
            btnSa ve = new QPushButton(centralWidget);
            btnSa ve->setObjectName(QString::fromUtf8("btnSa ve"));
            btnSa ve->setText("保存");
            buttonLayout->addWidget(btnSa ve);
            
            btnClear = new QPushButton(centralWidget);
            btnClear->setObjectName(QString::fromUtf8("btnClear"));
            btnClear->setText("清除");
            buttonLayout->addWidget(btnClear);
            
            btnCopy = new QPushButton(centralWidget);
            btnCopy->setObjectName(QString::fromUtf8("btnCopy"));
            btnCopy->setText("复制");
            buttonLayout->addWidget(btnCopy);
            
            leftLayout->addLayout(buttonLayout);
            horizontalLayout->addLayout(leftLayout, 2);
            
            // 右侧:设置区域
            rightLayout = new QVBoxLayout();
            rightLayout->setObjectName(QString::fromUtf8("rightLayout"));
            
            // 设置组
            groupSettings = new QGroupBox(centralWidget);
            groupSettings->setObjectName(QString::fromUtf8("groupSettings"));
            groupSettings->setTitle("设置");
            settingsLayout = new QVBoxLayout(groupSettings);
            
            // 版本
            layoutVersion = new QHBoxLayout();
            labelVersion = new QLabel(groupSettings);
            labelVersion->setText("版本:");
            layoutVersion->addWidget(labelVersion);
            
            comboVersion = new QComboBox(groupSettings);
            layoutVersion->addWidget(comboVersion);
            settingsLayout->addLayout(layoutVersion);
            
            // 纠错等级
            layoutECC = new QHBoxLayout();
            labelECC = new QLabel(groupSettings);
            labelECC->setText("纠错等级:");
            layoutECC->addWidget(labelECC);
            
            comboECC = new QComboBox(groupSettings);
            layoutECC->addWidget(comboECC);
            settingsLayout->addLayout(layoutECC);
            
            // 边距
            layoutBorder = new QHBoxLayout();
            labelBorder = new QLabel(groupSettings);
            labelBorder->setText("边距:");
            layoutBorder->addWidget(labelBorder);
            
            spinBorder = new QSpinBox(groupSettings);
            spinBorder->setRange(0, 20);
            spinBorder->setValue(4);
            layoutBorder->addWidget(spinBorder);
            settingsLayout->addLayout(layoutBorder);
            
            // 缩放
            layoutScale = new QHBoxLayout();
            labelScale = new QLabel(groupSettings);
            labelScale->setText("保存缩放:");
            layoutScale->addWidget(labelScale);
            
            spinScale = new QSpinBox(groupSettings);
            spinScale->setRange(1, 10);
            spinScale->setValue(4);
            layoutScale->addWidget(spinScale);
            settingsLayout->addLayout(layoutScale);
            
            // Logo设置
            layoutLogo = new QHBoxLayout();
            labelLogo = new QLabel(groupSettings);
            labelLogo->setText("Logo大小:");
            layoutLogo->addWidget(labelLogo);
            
            spinLogoSize = new QSpinBox(groupSettings);
            spinLogoSize->setRange(5, 50);
            spinLogoSize->setValue(20);
            spinLogoSize->setSuffix("%");
            layoutLogo->addWidget(spinLogoSize);
            
            btnAddLogo = new QPushButton(groupSettings);
            btnAddLogo->setText("添加");
            layoutLogo->addWidget(btnAddLogo);
            
            btnRemoveLogo = new QPushButton(groupSettings);
            btnRemoveLogo->setText("移除");
            layoutLogo->addWidget(btnRemoveLogo);
            settingsLayout->addLayout(layoutLogo);
            
            rightLayout->addWidget(groupSettings);
            
            // 样式组
            groupStyle = new QGroupBox(centralWidget);
            groupStyle->setObjectName(QString::fromUtf8("groupStyle"));
            groupStyle->setTitle("样式");
            styleLayout = new QVBoxLayout(groupStyle);
            
            checkRounded = new QCheckBox(groupStyle);
            checkRounded->setText("圆角模块");
            styleLayout->addWidget(checkRounded);
            
            checkGradient = new QCheckBox(groupStyle);
            checkGradient->setText("渐变颜色");
            styleLayout->addWidget(checkGradient);
            
            checkAutoPreview = new QCheckBox(groupStyle);
            checkAutoPreview->setText("实时预览");
            styleLayout->addWidget(checkAutoPreview);
            
            rightLayout->addWidget(groupStyle);
            
            // 信息组
            groupInfo = new QGroupBox(centralWidget);
            groupInfo->setObjectName(QString::fromUtf8("groupInfo"));
            groupInfo->setTitle("信息");
            infoLayout = new QVBoxLayout(groupInfo);
            
            labelCapacity = new QLabel(groupInfo);
            labelCapacity->setText("长度: 0/0");
            infoLayout->addWidget(labelCapacity);
            
            progressCapacity = new QProgressBar(groupInfo);
            progressCapacity->setRange(0, 100);
            infoLayout->addWidget(progressCapacity);
            
            rightLayout->addWidget(groupInfo);
            rightLayout->addStretch();
            
            horizontalLayout->addLayout(rightLayout, 1);
            verticalLayout->addLayout(horizontalLayout);
            
            MainWindow->setCentralWidget(centralWidget);
        }
    };
    #endif // UI_MAINWINDOW_H
    

    四、高级功能扩展

    4.1 批量生成工具

    // BatchQRCodeGenerator.h
    #ifndef BATCHQRCODEGENERATOR_H
    #define BATCHQRCODEGENERATOR_H
    
    #include 
    #include 
    #include 
    #include 
    
    class BatchQRCodeGenerator : public QObject, public QRunnable
    {
        Q_OBJECT
        
    public:
        struct BatchItem {
            QString id;
            QString content;
            QString filename;
            int version = 5;
            int eccLevel = 1;
            int scale = 4;
        };
        
        explicit BatchQRCodeGenerator(QObject *parent = nullptr);
        
        void addBatch(const QList& items);
        void clear();
        
        void run() override;
        
        void setOutputDir(const QString& dir) { m_outputDir = dir; }
        void setThreadCount(int count);
        
    signals:
        void progress(int current, int total, const QString& id);
        void finished(int successCount, int failedCount);
        void error(const QString& id, const QString& error);
        
    private:
        QList m_items;
        QString m_outputDir;
        QThreadPool m_threadPool;
    };
    #endif // BATCHQRCODEGENERATOR_H
    

    4.2 二维码解码功能

    // QRCodeDecoder.h
    #ifndef QRCODEDECODER_H
    #define QRCODEDECODER_H
    
    #include 
    #include 
    #include 
    
    class QRCodeDecoder : public QObject
    {
        Q_OBJECT
        
    public:
        explicit QRCodeDecoder(QObject *parent = nullptr);
        
        // 从图片文件解码
        QString decodeFromFile(const QString& filename);
        
        // 从QImage解码
        QString decodeFromImage(const QImage& image);
        
        // 从剪贴板解码
        QString decodeFromClipboard();
        
        // 从摄像头捕获
        void startCameraCapture();
        void stopCameraCapture();
        
    signals:
        void decoded(const QString& result);
        void cameraFrameCaptured(const QImage& frame);
        
    private:
        QZXing m_decoder;
    };
    #endif // QRCODEDECODER_H
    

    4.3 样式化二维码

    // StyledQRCodeGenerator.h
    #ifndef STYLEDQRCODEGENERATOR_H
    #define STYLEDQRCODEGENERATOR_H
    
    #include 
    
    class StyledQRCodeGenerator
    {
    public:
        enum PatternStyle {
            StyleDefault,
            StyleDots,
            StyleRounded,
            StyleStars,
            StyleHearts
        };
        
        struct StyleOptions {
            PatternStyle patternStyle = StyleDefault;
            QColor primaryColor = Qt::black;
            QColor secondaryColor = Qt::white;
            QColor gradientStart = Qt::black;
            QColor gradientEnd = Qt::darkGray;
            bool useGradient = false;
            int cornerRadius = 5;
        };
        
        static QImage generateStyledQRCode(const QString& text, 
                                          const QSize& size,
                                          const StyleOptions& options);
        
    private:
        static void applyPattern(QImage& image, const QImage& pattern, 
                                const QColor& color, int moduleSize);
        static QImage createDotPattern(int size);
        static QImage createStarPattern(int size);
        static QImage createHeartPattern(int size);
    };
    #endif // STYLEDQRCODEGENERATOR_H
    

    五、项目配置

    5.1 CMakeLists.txt

    cmake_minimum_required(VERSION 3.16)
    project(QRCodeGenerator)
    set(CMAKE_CXX_STANDARD 17)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    # 查找Qt
    find_package(Qt6 COMPONENTS Core Widgets REQUIRED)
    # 包含目录
    include_directories(${CMAKE_CURRENT_SOURCE_DIR}/qrcode)
    # 源文件
    set(SOURCES
        main.cpp
        QRCodeWidget.cpp
        MainWindow.cpp
        QRCodeGenerator.cpp
    )
    # 头文件
    set(HEADERS
        QRCodeWidget.h
        MainWindow.h
        QRCodeGenerator.h
    )
    # UI文件
    set(FORMS
        MainWindow.ui
    )
    # 资源文件
    set(RESOURCES
        resources.qrc
    )
    # 生成MOC文件
    qt6_wrap_cpp(MOC_SOURCES ${HEADERS})
    qt6_wrap_ui(UI_SOURCES ${FORMS})
    qt6_add_resources(RES_SOURCES ${RESOURCES})
    # 可执行文件
    add_executable(${PROJECT_NAME}
        ${SOURCES}
        ${MOC_SOURCES}
        ${UI_SOURCES}
        ${RES_SOURCES}
    )
    # 链接库
    target_link_libraries(${PROJECT_NAME}
        Qt6::Core
        Qt6::Widgets
    )

    5.2 .pro 文件 (qmake)

    # QRCodeGenerator.pro
    QT       += core gui
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    TARGET = QRCodeGenerator
    TEMPLATE = app
    # 源文件
    SOURCES += 
        main.cpp 
        QRCodeWidget.cpp 
        MainWindow.cpp
    HEADERS += 
        QRCodeWidget.h 
        MainWindow.h
    FORMS += 
        MainWindow.ui
    # 包含qrcode库
    INCLUDEPATH += $$PWD/qrcode
    # 编译选项
    QMAKE_CXXFLAGS += -std=c++17
    CONFIG += c++17
    # 发布配置
    CONFIG(release, debug|release) {
        DEFINES += QT_NO_DEBUG_OUTPUT
        QMAKE_CXXFLAGS += -O2
    }
    # 调试配置
    CONFIG(debug, debug|release) {
        DEFINES += QT_DEBUG
        QMAKE_CXXFLAGS += -g
    }

    5.3 资源文件

    
    
        
            
            icons/app.png
            icons/generate.png
            icons/sa ve.png
            icons/clear.png
            icons/logo.png
            
            styles/style.qss
            
            logo/default.png
        
    
    /* styles/style.qss */
    QMainWindow {
        background-color: #f5f5f5;
    }
    QGroupBox {
        font-weight: bold;
        border: 1px solid #ccc;
        border-radius: 5px;
        margin-top: 10px;
        padding-top: 10px;
    }
    QGroupBox::title {
        subcontrol-origin: margin;
        left: 10px;
        padding: 0 5px 0 5px;
    }
    QPushButton {
        padding: 8px 16px;
        border-radius: 4px;
        font-weight: bold;
    }
    QPushButton:hover {
        background-color: #e0e0e0;
    }
    QTextEdit {
        border: 1px solid #ccc;
        border-radius: 4px;
        padding: 8px;
        font-family: "Microsoft YaHei", "SimSun";
    }
    QProgressBar {
        border: 1px solid #ccc;
        border-radius: 4px;
        text-align: center;
    }
    QProgressBar::chunk {
        background-color: #4CAF50;
        border-radius: 4px;
    }

    六、使用示例

    6.1 基本使用

    #include "QRCodeGenerator.h"
    #include 
    #include 
    
    int main(int argc, char *argv[]) {
        QApplication app(argc, argv);
        
        // 创建二维码生成器
        QRCodeGenerator generator;
        
        // 生成基本二维码
        QImage qrCode = generator.generateQRCode("https://www.example.com", 
                                                QSize(200, 200));
        
        if (!qrCode.isNull()) {
            // 保存到文件
            qrCode.sa ve("qrcode.png");
            
            // 显示二维码
            QLabel label;
            label.setPixmap(QPixmap::fromImage(qrCode));
            label.show();
            
            return app.exec();
        }
        
        return 0;
    }
    

    6.2 高级功能

    // 高级使用示例
    void advancedExample() {
        QRCodeGenerator generator;
        
        // 1. 生成带Logo的二维码
        QImage logo(":/logo/company.png");
        QImage qrWithLogo = generator.generateQRCodeWithLogo(
            "https://www.company.com", logo, QSize(300, 300));
        
        // 2. 生成样式化二维码
        StyledQRCodeGenerator::StyleOptions options;
        options.patternStyle = StyledQRCodeGenerator::StyleDots;
        options.useGradient = true;
        options.gradientStart = QColor("#FF5722");
        options.gradientEnd = QColor("#FF9800");
        
        QImage styledQR = generator.generateStyledQRCode(
            "特殊样式", QSize(250, 250), options);
        
        // 3. 批量生成
        QList items;
        for (int i = 0; i < 10; i++) {
            BatchQRCodeGenerator::BatchItem item;
            item.id = QString("QR%1").arg(i+1);
            item.content = QString("https://example.com/item/%1").arg(i+1);
            item.filename = QString("qrcode_%1.png").arg(i+1);
            items.append(item);
        }
        
        BatchQRCodeGenerator batchGenerator;
        batchGenerator.addBatch(items);
        batchGenerator.setOutputDir("./qrcodes");
        
        QObject::connect(&batchGenerator, &BatchQRCodeGenerator::progress,
            int current, int total, const QString& id {
                qDebug() << "进度:" << current << "/" << total << id;
            });
        
        batchGenerator.run();
    }
    

    6.3 命令行工具

    // QRCodeCLI.cpp - 命令行工具
    #include "QRCodeGenerator.h"
    #include 
    #include 
    #include 
    
    int main(int argc, char *argv[]) {
        QCoreApplication app(argc, argv);
        app.setApplicationName("QR Code CLI");
        app.setApplicationVersion("1.0.0");
        
        QCommandLineParser parser;
        parser.setApplicationDescription("命令行二维码生成器");
        parser.addHelpOption();
        parser.addVersionOption();
        
        // 定义参数
        parser.addPositionalArgument("content", "要编码的内容");
        parser.addPositionalArgument("output", "输出文件", "[output.png]");
        
        QCommandLineOption sizeOption("s", "图片大小", "size", "200");
        parser.addOption(sizeOption);
        
        QCommandLineOption versionOption("v", "二维码版本", "version", "5");
        parser.addOption(versionOption);
        
        QCommandLineOption eccOption("e", "纠错等级", "ecc", "1");
        parser.addOption(eccOption);
        
        QCommandLineOption logoOption("l", "Logo文件", "logo");
        parser.addOption(logoOption);
        
        parser.process(app);
        
        // 获取参数
        QStringList args = parser.positionalArguments();
        if (args.isEmpty()) {
            parser.showHelp(1);
        }
        
        QString content = args.at(0);
        QString output = args.value(1, "qrcode.png");
        int size = parser.value(sizeOption).toInt();
        int version = parser.value(versionOption).toInt();
        int ecc = parser.value(eccOption).toInt();
        QString logoFile = parser.value(logoOption);
        
        // 生成二维码
        QRCodeGenerator generator;
        QImage qrCode;
        
        if (!logoFile.isEmpty()) {
            QImage logo(logoFile);
            if (logo.isNull()) {
                qCritical() << "无法加载Logo文件:" << logoFile;
                return 1;
            }
            qrCode = generator.generateQRCodeWithLogo(content, logo, QSize(size, size));
        } else {
            qrCode = generator.generateQRCode(content, QSize(size, size), version, ecc);
        }
        
        if (qrCode.isNull()) {
            qCritical() << "生成二维码失败";
            return 1;
        }
        
        if (qrCode.sa ve(output)) {
            qInfo() << "二维码已保存到:" << output;
            return 0;
        } else {
            qCritical() << "保存失败:" << output;
            return 1;
        }
    }
    
    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 解决方案
    相关文章 更多
    精品专题 更多
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    macOS软件

    正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

    IOS软件

    正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

    AI

    正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

    Mac软件 更多
    IntelliJ IDEA macOS版
    IntelliJ IDEA macOS版

    IntelliJ IDEA 是 JetBrains 推出的专业集成开发环境,重点服务于 Java、Kotlin 与 JVM 项目开发。软件集成代码补全、静态检查、重构、调试、测试、版本控制及构建工具,并可借助插件扩展语言和框架支持。

    PyCharm macOS版
    PyCharm macOS版

    JetBrains PyCharm 是面向 Python 开发者的集成开发环境,提供智能补全、代码检查、重构、调试、测试、版本控制及虚拟环境管理功能。Mac 版兼容 Intel 与 Apple 芯片,核心功能可免费使用。

    WebStorm macOS版
    WebStorm macOS版

    JetBrains WebStorm 是面向 JavaScript、TypeScript 和现代 Web 技术的专业集成开发环境,可智能理解项目结构,提供代码补全、重构、错误检查、运行调试、测试及 Git 工具。

    After Effects macOS版
    After Effects macOS版

    Adobe After Effects 是面向动态图形、影视特效与视频合成的专业创作软件。它提供关键帧动画、遮罩抠像、运动跟踪、三维空间、文字动画和表达式等工具,并可与 Premiere Pro、Photoshop、Illustrator

    Audition macOS版
    Audition macOS版

    Adobe Audition 是面向播客、影视后期、音乐制作及内容创作者的专业音频工作站,提供波形精修、多轨录制与混音、频谱编辑、降噪修复、响度匹配和效果处理工具,并可与 Adobe Premiere 协同完成视频声音制作。

    Bridge macOS版
    Bridge macOS版

    Adobe Bridge 是面向摄影师、设计师及内容团队的免费数字资产管理工具,可集中预览照片、视频和 Adobe 项目文件,并利用评级、标签、关键词、元数据、筛选与收藏集完成分类检索。它还支持批量重命名、格式导出、相机导入及 Camera

    Illustrator macOS版
    Illustrator macOS版

    Adobe Illustrator 是 Adobe 推出的专业矢量图形设计软件,适合在 Mac 上制作标志、图标、插画、包装、信息图及印刷版面。它以路径和锚点构建可无损缩放的图形,并提供钢笔、形状、文字、图像描摹、渐变、画板及生成式功能。

    InDesign macOS版
    InDesign macOS版

    Adobe InDesign 是面向印刷品与数字出版物的专业版面设计软件,可在 Mac 上制作书籍、杂志、宣传册、海报、报告及交互式文档。它提供精细的文字样式、网格、母版、长文档管理和印前输出能力。

    Lightroom Classic macOS版
    Lightroom Classic macOS版

    Adobe Lightroom Classic 是面向桌面摄影工作流的照片管理与后期处理软件,可将原始照片保存在本地硬盘,通过目录、关键词、评分和收藏夹高效整理图库,并提供 RAW 冲印、蒙版、镜头校正、批量同步及多格式导出等功能。

    Media Encoder macOS版
    Media Encoder macOS版

    Adobe Media Encoder 是 Adobe 推出的专业音视频编码与转码工具,可通过队列、预设和监视文件夹批量完成格式转换、代理文件创建及多平台成片输出,并与 Premiere Pro、After Effects 等软件紧密协作。

    Photoshop macOS版
    Photoshop macOS版

    Adobe Photoshop 是面向摄影师、设计师和内容创作者的专业图像处理软件,提供图层、蒙版、选区、修复、调色、文字排版、智能对象及生成式编辑等能力。Mac 版支持 Intel 与 Apple Silicon 处理器。

    Premiere Pro macOS版
    Premiere Pro macOS版

    Adobe Premiere Pro 是面向专业视频制作的非线性剪辑软件,提供多轨时间线、调色、音频处理、字幕、代理工作流和多格式输出能力,并可与 After Effects、Audition、Photoshop 及 Frame.io 协同

    WINDOWS 更多
    IntelliJ IDEA Windows版
    IntelliJ IDEA Windows版

    JetBrains IntelliJ IDEA 是以 Java、Kotlin 和 JVM 项目为核心的专业集成开发环境,提供智能补全、代码检查、安全重构、调试、测试、版本控制及构建工具集成。统一发行版的核心功能可免费用于商业和非商业项目,

    PhpStorm Windows版
    PhpStorm Windows版

    PhpStorm 是 JetBrains 面向 PHP 与现代 Web 开发打造的专业集成开发环境,提供代码补全、静态检查、重构、调试、测试、数据库、版本控制及前端语言支持。Windows 用户可直接下载安装程序,

    PyCharm Windows版
    PyCharm Windows版

    PyCharm 是 JetBrains 推出的 Python 集成开发环境,提供智能代码补全、错误检查、重构、调试、测试、Git、终端及 Jupyter Notebook 支持。统一版安装后可体验 30 天 Pro 功能,

    WebStorm Windows版
    WebStorm Windows版

    WebStorm 是 JetBrains 面向 JavaScript、TypeScript 和现代 Web 技术打造的集成开发环境。它提供项目级代码分析、智能补全、安全重构、导航搜索,并集成调试、测试、终端、Git 与常用前端工具,

    Photoshop Windows版
    Photoshop Windows版

    Adobe Photoshop 是面向摄影师、设计师和内容创作者的专业图像处理工具,可在 Windows 上完成照片修饰、选区抠图、图层合成、文字排版、绘画及生成式编辑。软件采用订阅授权,由 Creative Cloud 管理安装、更新与许

    InDesign Windows版
    InDesign Windows版

    Adobe InDesign 是面向印刷与数字出版的专业页面排版工具,可制作书籍、杂志、宣传册、海报、交互式 PDF 和电子书。它提供精细的文字样式、多页面管理、印前检查及多格式输出能力,并能与 Photoshop、Illustrator

    Illustrator Windows版
    Illustrator Windows版

    Adobe Illustrator 是用于绘制矢量图形、插画、图标、徽标和版式的专业设计工具。它以路径和锚点为核心,作品放大后仍能保持清晰,并提供画板、文字、渐变、图像描摹及精确变换等功能,适合品牌视觉、印刷物料、数字界面和商业插画创作。

    Bridge Windows版
    Bridge Windows版

    Adobe Bridge 是 Adobe 推出的创意资产管理工具,可集中预览、分类和查找照片、视频、PDF及多种设计文件,并支持元数据、关键词、评级、批量重命名和格式导出。它可与 Photoshop、Illustrator 等应用衔接,

    Lightroom Classic Windows版
    Lightroom Classic Windows版

    Adobe Lightroom Classic 是面向 Windows 桌面摄影工作流的照片管理与无损编辑工具,可通过目录集中整理大型图库,并完成 RAW 显影、局部蒙版、批量调整、打印和多格式导出。它强调本地文件管理与精细控制,

    Acrobat Pro Windows版
    Acrobat Pro Windows版

    Adobe Acrobat Pro 是面向专业 PDF 工作的综合解决方案,可在 Windows 中创建、编辑、转换、比较、整理和保护文档,并支持表单、电子签名、扫描件文字识别及敏感信息永久遮盖。订阅还包含网页、移动服务和云端协作能力,

    After Effects Windows版
    After Effects Windows版

    Adobe After Effects 是面向动态图形、动画与影视视觉特效制作的专业工具,可完成关键帧动画、图层合成、遮罩跟踪、抠像、文字动画和二维三维元素整合。Windows 版通过 Adobe Creative Cloud 安装及更新,

    Media Encoder Windows版
    Media Encoder Windows版

    Adobe Media Encoder 是 Adobe 面向视频与音频制作流程提供的专业编码和转码工具,可批量处理媒体文件、创建代理、套用输出预设并监控文件夹自动执行任务。它与 Premiere、After Effects、Audition