——今天的我们,是站在巨人的肩膀上前行。
二维码自从出现以来,已经极大地改变了我们的生活方式,它能容纳一些简短的信息,却又不那么简短,以至于很多场合都能使用二维码作为信息的载体。一个月以前,有个老师跟我提过一句,如果可以在上机实验时使用二维码来绑定学生的信息,就可以省很多时间。于是我就萌生了使用Qt绘制二维码的想法。
但是这一个月来我一直在研究另一个东西,直到昨天我才研究出一点进展。那个做好之后我就开始研究如何使用Qt生成二维码,发现二维码是有不同标准的,比如在二维码符号表示技术研究方面已研制出多种码制,常见的有PDF417、QR Code、Code 49、Code 16K、Code One等。常用的二维码相关的库也有很多zbar、zxing、libqrencode等。
这次我选用了Github上的 Nayuki 大神所写的QRcode库c++版本,放入Qt中,实现了承载指定信息的二维码的绘制功能。下面是一些总结。
一、QR Code码
QR Code码,是由Denso公司于1994年9月研制的一种矩阵二维码符号,它具有一维条码及其它二维条码所具有的信息容量大、可靠性高、可表示汉字及图象多种文字信息、保密防伪性强等优点。
二、二维码生成库的源码
Github上的大佬 Nayuki:https://github.com/nayuki 提供了QR Code码相关的图片生成库,包含了C、C++、Java、JavaScript 、Python 、Rust 等语言的各个版本,代码简洁清晰,质量非常高。
我也把这份代码fork到了我的仓库中,如果想重现我的操作也可以从我的Github主页上获取相关的源代码 https://github.com/gengyuchao/QR-Code-generator
本次我使用的是c++版本的代码 文件夹名为cpp
三、创建Qt工程
1、在windows下创建Qt工程
点击下一步直至完成
2、添加库源文件
将下载的 QR-Code-generator-master.zip 中的 cpp文件夹里的
“BitBuffer.cpp”、“BitBuffer.hpp”、
“QrCode.cpp”、“QrCode.hpp”、
“QrSegment.cpp”、“QrSegment.hpp”、
解压到工程目录“G:\Qt_Project\Create_QRcode”下
最一开始的工程目录是这样子的,然后我们在工程文件夹上右击,选择Add Existing Directory 把刚刚解压的库文件添加进去
取消勾选已有的 main.cpp 、mainwindows.cpp 、mainwindows.h 然后 点击OK即可
添加后的工程目录变成了这样
运行之后发现没有错误(如果你不小心在上一步直接点了OK、工程会报错,原因是重复添加了之前的文件 右击打开pro文件 删除重复的 main.cpp 、mainwindows.cpp 、mainwindows.h 即可)
3、编写二维码绘制函数
根据库的说明文档,我们可以知道这个库的使用方法如下:
C++ language:
#include <string>
#include <vector>
#include "QrCode.hpp"
using namespace qrcodegen;
// Simple operation
QrCode qr0 = QrCode::encodeText("Hello, world!", QrCode::Ecc::MEDIUM);
std::string svg = qr0.toSvgString(4);
// Manual operation
std::vector<QrSegment> segs =
QrSegment::makeSegments("3141592653589793238462643383");
QrCode qr1 = QrCode::encodeSegments(
segs, QrCode::Ecc::HIGH, 5, 5, 2, false);
for (int y = 0; y < qr1.getSize(); y++) {
for (int x = 0; x < qr1.getSize(); x++) {
(... paint qr1.getModule(x, y) ...)
}
}
添加头文件#include <string> #include <vector> #include "QrCode.hpp" 使用命名空间
using namespace qrcodegen;
然后就可以使用下面的函数了
于是我创建了函数 void Show_QRcode_Picture() 并把它添加进 mainwindows.h头文件中
void MainWindow::Show_QRcode_Picture()
{
// Manual operation
std::vector<QrSegment> segs =
QrSegment::makeSegments("3141592653589793238462643383");
QrCode qr1 = QrCode::encodeSegments(
segs, QrCode::Ecc::HIGH, 5, 5, 2, false);
for (int y = 0; y < qr1.getSize(); y++) {
for (int x = 0; x < qr1.getSize(); x++) {
//(... paint qr1.getModule(x, y) ...)
}
}
}
将实例代码添加进去
我的方案是
使用Qt的QImage进行图像的编辑 ->转换为QPixmap-> 在QLabel中显示
4、在mainwindows.ui中添加控件
添加QLabel、QTextEdit和一个Button按钮
5、代码实现
//添加头文件:
#include "QImage"
//创建二维码画布
QImage QrCode_Image=QImage(qr1.getSize(),qr1.getSize(),QImage::Format_RGB888);
//图像大小转换为适当的大小
QrCode_Image=QrCode_Image.scaled(ui->label->width(),ui->label->height(),
Qt::KeepAspectRatio);
//转换为QPixmap在Label中显示
ui->label->setPixmap(QPixmap::fromImage(QrCode_Image));
完整代码如下:
void MainWindow::Show_QRcode_Picture(QString message)
{
// Manual operation
std::vector<QrSegment> segs =
QrSegment::makeSegments(message.toLatin1());
QrCode qr1 = QrCode::encodeSegments(
segs, QrCode::Ecc::HIGH, 5, 5, 2, false);
//创建二维码画布
QImage QrCode_Image=QImage(qr1.getSize(),qr1.getSize(),QImage::Format_RGB888);
for (int y = 0; y < qr1.getSize(); y++) {
for (int x = 0; x < qr1.getSize(); x++) {
if(qr1.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));
}
void MainWindow::on_Create_Button_clicked()
{
Show_QRcode_Picture(ui->textEdit->toPlainText());
}
6、需要注意
下面内容摘自百度百科:
1、符号规格从版本1(21×21模块)到版本40(177×177 模块),每提高一个版本,每边增加4个模块。
2、数据类型与容量(参照最大规格符号版本40-L级):
数字数据:7,089个字符
字母数据: 4,296个字符
8位字节数据: 2,953个字符
汉字数据:1,817个字符
3、数据表示方法:
深色模块表示二进制"1",浅色模块表示二进制"0"。
4、纠错能力:
L级:约可纠错7%的数据码字
M级:约可纠错15%的数据码字
Q级:约可纠错25%的数据码字
H级:约可纠错30%的数据码字
5、结构链接(可选)
可用1-16个QR Code码符号表示一组信息。每一符号表示100个字符的信息。
当前的规格为5,如果你的内容超过了最大数据量,就会造成程序崩溃。如果需要在二维码中添加更多的信息,你可以适当地修改模块版本,以增大数据容量。

至此,我们的二维码生成器就做好了。欢迎大家和我一起交流讨论。整个工程我已经上传至我的Github主页上(https://github.com/gengyuchao/Create_QRcode),欢迎访问~