C++/QT生成二维码和扫瞄二维码

发布于:2023-02-06 ⋅ 阅读:(1184) ⋅ 点赞:(0)

本次使用Qt实现生成二维码和扫瞄二维码
在这里插入图片描述

完整代码参考git: https://github.com/lzglocal/QRCODE.git



一. 创建工程项目

  1. 选择QT Widgets Application
    在这里插入图片描述

  2. 类名和选择基类,我这里选择默认的QMainwindow
    在这里插入图片描述
    在这里插入图片描述

  3. 创建完工程后,双击qrcode_app.ui文件,编辑ui
    添加三个PushButton 命名分别为generator_qrcode_pbtn、copy_pic_pbtn、qrcode_scan_pbtn
    一个Label
    一个TextLine
    在这里插入图片描述

  4. 自己自由布局
    在这里插入图片描述

  5. 添加qrc资源文件,和添加应用程序图标
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述



二 .QRCODE库

  1. 生成二维码使用了nayuki 的QR Code码相关的cpp库:git地址:https://github.com/nayuki/QR-Code-generator.git

  2. 扫码二维码使用了qzxing的git库:git地址: https://github.com/ftylitak/qzxing.git



三. 添加生成二维码库

  1. git clone https://github.com/nayuki/QR-Code-generator.git
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

四. 生成二维码和复制二维码实现

参考QrCodeGeneratorDemo.cpp

  1. Ui文件pushbutton三个按钮转到槽函数
    在这里插入图片描述
    在这里插入图片描述

  2. 编辑头文件qrcode_app.h

#ifndef QRCODE_APP_H
#define QRCODE_APP_H
#include <QMainWindow>
//#include <climits>
//#include <cstdint>
//#include <cstdlib>
#include <cstring>
//#include <iostream>
//#include <sstream>
//#include <string>
//#include <vector>
#include "qrcodegen.h"
#include <QImage>
#include <QClipboard>
#include <QFileDialog>
//#include <QDebug>
using std::uint8_t;
using qrcodegen::QrCode;
using qrcodegen::QrSegment;

QT_BEGIN_NAMESPACE
namespace Ui { class Qrcode_app; }
QT_END_NAMESPACE
class Qrcode_app : public QMainWindow
{
 Q_OBJECT
public:
 Qrcode_app(QWidget *parent = nullptr);
 ~Qrcode_app();
 
private slots:
 //点击生成二维码槽函数
 void on_generator_qrcode_pbtn_clicked();
 //点击复制二维码
 void on_copy_pic_pbtn_clicked();
 //点击选择二维码扫码
 void on_qrcode_scan_pbtn_clicked();

private:
 Ui::Qrcode_app *ui;
 
//    QString toSvgString(const QrCode &qr, int border);
//    void printQr(const QrCode &qr);
//生成二维码和复制二维码功能函数
 void doBasicDemo(bool is_copy=false);
 
//    void doVarietyDemo();
//    void doSegmentDemo();
//    void doMaskDemo();
};
#endif // QRCODE_APP_H


  1. 编辑源文件qrcode_app.cpp
#include "qrcode_app.h"
#include "ui_qrcode_app.h"

// Function prototypes
//static void doBasicDemo();
#include <QProcess>
#include <QDesktopServices>
#include <QMessageBox>


Qrcode_app::Qrcode_app(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::Qrcode_app)
{
    ui->setupUi(this);
}

Qrcode_app::~Qrcode_app()
{
    delete ui;
}


/*---- Demo suite ----*/

// Creates a single QR Code, then prints it to the console.
//生成二维码和复制二维码功能函数
void Qrcode_app::doBasicDemo(bool is_copy) {

    const char *text = (ui->textEdit->toPlainText()).toLocal8Bit();              // User-supplied text
    const QrCode::Ecc errCorLvl = QrCode::Ecc::LOW;  // Error correction level

    // Make and print the QR Code symbol
    const QrCode qr = QrCode::encodeText(text, errCorLvl);
//    printQr(qr);

    QImage QrCode_Image=QImage(qr.getSize(),qr.getSize(),QImage::Format_RGB888);
    for (int y = 0; y < qr.getSize(); y++) {
        for (int x =0; x < qr.getSize(); x++) {
            if(qr.getModule(x, y)==0){
                QrCode_Image.setPixel(x,y,qRgb(255,255,255));
            }else{
                QrCode_Image.setPixel(x,y,qRgb(0,0,0));
            }
        }
    }

    //图像大小转换为适当的大小
        QrCode_Image=QrCode_Image.scaled(ui->label->width(),ui->label->height(),
                        Qt::KeepAspectRatio);
        //转换为QPixmap在Label中显示
        ui->label->setPixmap(QPixmap::fromImage(QrCode_Image));
        //如果为真,则是拷贝操作
        if(is_copy){
            QClipboard *clip=QApplication::clipboard();
            clip->setPixmap(QPixmap::fromImage(QrCode_Image));
        }
}


 Creates a variety of QR Codes that exercise different features of the library, and prints each one to the console.
//void Qrcode_app::doVarietyDemo() {
//    // Numeric mode encoding (3.33 bits per digit)
//    const QrCode qr0 = QrCode::encodeText("314159265358979323846264338327950288419716939937510", QrCode::Ecc::MEDIUM);
//    printQr(qr0);

//    // Alphanumeric mode encoding (5.5 bits per character)
//    const QrCode qr1 = QrCode::encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", QrCode::Ecc::HIGH);
//    printQr(qr1);

//    // Unicode text as UTF-8
//    const QrCode qr2 = QrCode::encodeText("\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1wa\xE3\x80\x81"
//        "\xE4\xB8\x96\xE7\x95\x8C\xEF\xBC\x81\x20\xCE\xB1\xCE\xB2\xCE\xB3\xCE\xB4", QrCode::Ecc::QUARTILE);
//    printQr(qr2);

//    // Moderately large QR Code using longer text (from Lewis Carroll's Alice in Wonderland)
//    const QrCode qr3 = QrCode::encodeText(
//        "Alice was beginning to get very tired of sitting by her sister on the bank, "
//        "and of having nothing to do: once or twice she had peeped into the book her sister was reading, "
//        "but it had no pictures or conversations in it, 'and what is the use of a book,' thought Alice "
//        "'without pictures or conversations?' So she was considering in her own mind (as well as she could, "
//        "for the hot day made her feel very sleepy and stupid), whether the pleasure of making a "
//        "daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly "
//        "a White Rabbit with pink eyes ran close by her.", QrCode::Ecc::HIGH);
//    printQr(qr3);
//}


 Creates QR Codes with manually specified segments for better compactness.
//void Qrcode_app::doSegmentDemo() {
//    // Illustration "silver"
//    const char *silver0 = "THE SQUARE ROOT OF 2 IS 1.";
//    const char *silver1 = "41421356237309504880168872420969807856967187537694807317667973799";
//    const QrCode qr0 = QrCode::encodeText(
//        (std::string(silver0) + silver1).c_str(),
//        QrCode::Ecc::LOW);
//    printQr(qr0);

//    const QrCode qr1 = QrCode::encodeSegments(
//        {QrSegment::makeAlphanumeric(silver0), QrSegment::makeNumeric(silver1)},
//        QrCode::Ecc::LOW);
//    printQr(qr1);

//    // Illustration "golden"
//    const char *golden0 = "Golden ratio \xCF\x86 = 1.";
//    const char *golden1 = "6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374";
//    const char *golden2 = "......";
//    const QrCode qr2 = QrCode::encodeText(
//        (std::string(golden0) + golden1 + golden2).c_str(),
//        QrCode::Ecc::LOW);
//    printQr(qr2);

//    std::vector<uint8_t> bytes(golden0, golden0 + std::strlen(golden0));
//    const QrCode qr3 = QrCode::encodeSegments(
//        {QrSegment::makeBytes(bytes), QrSegment::makeNumeric(golden1), QrSegment::makeAlphanumeric(golden2)},
//        QrCode::Ecc::LOW);
//    printQr(qr3);

//    // Illustration "Madoka": kanji, kana, Cyrillic, full-width Latin, Greek characters
//    const char *madoka =  // Encoded in UTF-8
//        "\xE3\x80\x8C\xE9\xAD\x94\xE6\xB3\x95\xE5"
//        "\xB0\x91\xE5\xA5\xB3\xE3\x81\xBE\xE3\x81"
//        "\xA9\xE3\x81\x8B\xE2\x98\x86\xE3\x83\x9E"
//        "\xE3\x82\xAE\xE3\x82\xAB\xE3\x80\x8D\xE3"
//        "\x81\xA3\xE3\x81\xA6\xE3\x80\x81\xE3\x80"
//        "\x80\xD0\x98\xD0\x90\xD0\x98\xE3\x80\x80"
//        "\xEF\xBD\x84\xEF\xBD\x85\xEF\xBD\x93\xEF"
//        "\xBD\x95\xE3\x80\x80\xCE\xBA\xCE\xB1\xEF"
//        "\xBC\x9F";
//    const QrCode qr4 = QrCode::encodeText(madoka, QrCode::Ecc::LOW);
//    printQr(qr4);

//    const std::vector<int> kanjiChars{  // Kanji mode encoding (13 bits per character)
//        0x0035, 0x1002, 0x0FC0, 0x0AED, 0x0AD7,
//        0x015C, 0x0147, 0x0129, 0x0059, 0x01BD,
//        0x018D, 0x018A, 0x0036, 0x0141, 0x0144,
//        0x0001, 0x0000, 0x0249, 0x0240, 0x0249,
//        0x0000, 0x0104, 0x0105, 0x0113, 0x0115,
//        0x0000, 0x0208, 0x01FF, 0x0008,
//    };
//    qrcodegen::BitBuffer bb;
//    for (int c : kanjiChars)
//        bb.appendBits(static_cast<std::uint32_t>(c), 13);
//    const QrCode qr5 = QrCode::encodeSegments(
//        {QrSegment(QrSegment::Mode::KANJI, static_cast<int>(kanjiChars.size()), bb)},
//        QrCode::Ecc::LOW);
//    printQr(qr5);
//}


 Creates QR Codes with the same size and contents but different mask patterns.
//void Qrcode_app::doMaskDemo() {
//    // Project Nayuki URL
//    std::vector<QrSegment> segs0 = QrSegment::makeSegments("https://www.nayuki.io/");
//    printQr(QrCode::encodeSegments(segs0, QrCode::Ecc::HIGH, QrCode::MIN_VERSION, QrCode::MAX_VERSION, -1, true));  // Automatic mask
//    printQr(QrCode::encodeSegments(segs0, QrCode::Ecc::HIGH, QrCode::MIN_VERSION, QrCode::MAX_VERSION, 3, true));  // Force mask 3

//    // Chinese text as UTF-8
//    std::vector<QrSegment> segs1 = QrSegment::makeSegments(
//        "\xE7\xB6\xAD\xE5\x9F\xBA\xE7\x99\xBE\xE7\xA7\x91\xEF\xBC\x88\x57\x69\x6B\x69\x70"
//        "\x65\x64\x69\x61\xEF\xBC\x8C\xE8\x81\x86\xE8\x81\xBD\x69\x2F\xCB\x8C\x77\xC9\xAA"
//        "\x6B\xE1\xB5\xBB\xCB\x88\x70\x69\xCB\x90\x64\x69\x2E\xC9\x99\x2F\xEF\xBC\x89\xE6"
//        "\x98\xAF\xE4\xB8\x80\xE5\x80\x8B\xE8\x87\xAA\xE7\x94\xB1\xE5\x85\xA7\xE5\xAE\xB9"
//        "\xE3\x80\x81\xE5\x85\xAC\xE9\x96\x8B\xE7\xB7\xA8\xE8\xBC\xAF\xE4\xB8\x94\xE5\xA4"
//        "\x9A\xE8\xAA\x9E\xE8\xA8\x80\xE7\x9A\x84\xE7\xB6\xB2\xE8\xB7\xAF\xE7\x99\xBE\xE7"
//        "\xA7\x91\xE5\x85\xA8\xE6\x9B\xB8\xE5\x8D\x94\xE4\xBD\x9C\xE8\xA8\x88\xE7\x95\xAB");
//    printQr(QrCode::encodeSegments(segs1, QrCode::Ecc::MEDIUM, QrCode::MIN_VERSION, QrCode::MAX_VERSION, 0, true));  // Force mask 0
//    printQr(QrCode::encodeSegments(segs1, QrCode::Ecc::MEDIUM, QrCode::MIN_VERSION, QrCode::MAX_VERSION, 1, true));  // Force mask 1
//    printQr(QrCode::encodeSegments(segs1, QrCode::Ecc::MEDIUM, QrCode::MIN_VERSION, QrCode::MAX_VERSION, 5, true));  // Force mask 5
//    printQr(QrCode::encodeSegments(segs1, QrCode::Ecc::MEDIUM, QrCode::MIN_VERSION, QrCode::MAX_VERSION, 7, true));  // Force mask 7
//}



///*---- Utilities ----*/

 Returns a string of SVG code for an image depicting the given QR Code, with the given number
 of border modules. The string always uses Unix newlines (\n), regardless of the platform.
//QString Qrcode_app::toSvgString(const QrCode &qr, int border) {
//    if (border < 0)
//        throw std::domain_error("Border must be non-negative");
//    if (border > INT_MAX / 2 || border * 2 > INT_MAX - qr.getSize())
//        throw std::overflow_error("Border too large");

//    QString sb;
//    sb + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
//    sb + "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n";
//    sb + "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 ";
//    sb + (qr.getSize() + border * 2) + " " + (qr.getSize() + border * 2) + "\" stroke=\"none\">\n";
//    sb + "\t<rect width=\"100%\" height=\"100%\" fill=\"#FFFFFF\"/>\n";
//    sb + "\t<path d=\"";
//    for (int y = 0; y < qr.getSize(); y++) {
//        for (int x = 0; x < qr.getSize(); x++) {
//            if (qr.getModule(x, y)) {
//                if (x != 0 || y != 0)
//                    sb + " ";
//                sb + "M" + (x + border) + "," + (y + border) + "h1v1h-1z";
//            }
//        }
//    }
//    sb + "\" fill=\"#000000\"/>\n";
//    sb + "</svg>\n";
//    return sb;
//}


 Prints the given QrCode object to the console.
//void Qrcode_app::printQr(const QrCode &qr) {

//    QImage QrCode_Image=QImage(qr.getSize(),qr.getSize(),QImage::Format_RGB888);
//    for (int y = 0; y < qr.getSize(); y++) {
//        for (int x = 0; x < qr.getSize(); x++) {
//            if(qr.getModule(x, y)==0){
//                QrCode_Image.setPixel(x,y,qRgb(255,255,255));
//            }else{
//                QrCode_Image.setPixel(x,y,qRgb(0,0,0));
//            }
//        }
//        //图像大小转换为适当的大小
//        QrCode_Image=QrCode_Image.scaled(ui->label->width(),ui->label->height(),
//                                         Qt::KeepAspectRatio);
//        //转换为QPixmap在Label中显示
//        ui->label->setPixmap(QPixmap::fromImage(QrCode_Image));
//    }
//    qDebug()<<toSvgString(qr, 4);
//}   

//生成二维码槽函数
void Qrcode_app::on_generator_qrcode_pbtn_clicked(){
    doBasicDemo();
}

//复制二维码槽函数
void Qrcode_app::on_copy_pic_pbtn_clicked(){
    doBasicDemo(true);
}
  1. 测试
    在这里插入图片描述

打开绘图工具粘贴,复制二维码也没有问题
在这里插入图片描述

五. 添加扫码二维码库

git clone https://github.com/ftylitak/qzxing.git
在这里插入图片描述
在这里插入图片描述

  1. 把源码添加到工程目录
    在这里插入图片描述
    在这里插入图片描述

  2. 工程文件pro中包含
    在这里插入图片描述



六. 扫码二维码代码实现

  1. 源文件文件qrcode_app.cpp中
    添加头文件 #include “QZXing.h”
#include "QZXing.h"

在这里插入图片描述

  1. 点击槽函数代码实现
    在这里插入图片描述
//扫码二维码槽函数
void Qrcode_app::on_qrcode_scan_pbtn_clicked()
{
    //选择图片文件
    QString filename = QFileDialog::getOpenFileName(this,"file","./","any files(*.*)"";;any files(*.png)");
    QImage img;
    if(!(img.load(filename))){
            return;
    }
    img = img.scaled(ui->label->width(),ui->label->height(),Qt::KeepAspectRatio);
    //加载选择的图片显示到label标签
    ui->label->setPixmap(QPixmap::fromImage(img));

//    QImage imageToDecode(filename);
    QZXing decoder;
    decoder.setDecoder( QZXing::DecoderFormat_QR_CODE | QZXing::DecoderFormat_EAN_13 );
    decoder.setSourceFilterType(QZXing::SourceFilter_ImageNormal);
    decoder.setTryHarderBehaviour(QZXing::TryHarderBehaviour_ThoroughScanning | QZXing::TryHarderBehaviour_Rotate);


//    decoder.setDecoder( QZXing::DecoderFormat_CODE_128 | QZXing::DecoderFormat_QR_CODE);
    QString result = decoder.decodeImage(img);
    if(result.isEmpty()){
        QMessageBox::about(this,"warning","Wrong picture format!");
        return;
    }
    //扫码结果显示textEdit
    ui->textEdit->setText(result);
}
  1. main函数编写只能运行一个程序
#include "qrcode.h"
#include <QSharedMemory>
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
     //创建运行时只允许存在一个程序
    static QSharedMemory *shareMem = new QSharedMemory("SingleAPP");
    //判断如果存在存直接退出
    if(!shareMem->create(1)){
        qApp->quit();
        return -1;
    }else{
        int result = -1;
        while (result !=0) {
            Create_qrcode w;
            w.setWindowIcon(QIcon(":/images/main_logo.ico"));
            w.show();
            result= a.exec();  //!退出时如果为零,正常退出,否则重启程序
        }
        return result;
    }
}

完整代码参考git: https://github.com/lzglocal/QRCODE.git



七. 测试

选择刚刚保存的二维码
在这里插入图片描述

在这里插入图片描述



八. 打包发布

参考1:生成有一个应用安装包

参考2:生成一个执行程序

本文含有隐藏内容,请 开通VIP 后查看