如何在原生 C/C++ 中使用 Qt 绘制二维码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21400254/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to draw a QR code with Qt in native C/C++
提问by Lennart Rolland
QR in Qt
Qt中的二维码
As a companion question to How to scan for QR codes with Qt, I want to know how to draw a QR codefrom native C/C++ code in my Qt5 based desktop app, but I could not find an example of how to do this.
作为如何使用 Qt 扫描二维码的伴随问题,我想知道如何在基于 Qt5 的桌面应用程序中从本机 C/C++ 代码绘制二维码,但我找不到如何执行此操作的示例。
I know QtQRexists, but it has dependencies on python-qrtoolswhich in my opinion kind of defeats the purpose of using Qt in the first place. I want a nimble, efficient and dependency-free solution that will compile with my app wherever I decided to take it.
我知道QtQR存在,但它依赖于python-qrtools,在我看来这首先违背了使用 Qt 的目的。我想要一个灵活、高效且无依赖性的解决方案,它可以在我决定采用的任何地方与我的应用程序一起编译。
How can I do that?
我怎样才能做到这一点?
采纳答案by Nayuki
If you feel that Fukuchi's library is too large[0]for you, consider looking at Nayuki's C++ QR Code generator library[1]: https://github.com/nayuki/QR-Code-generator/tree/master/cpp
如果你觉得 Fukuchi 的库对你来说太大[0],可以考虑看看 Nayuki 的 C++ QR 码生成器库[1]:https: //github.com/nayuki/QR-Code-generator/tree/master/cpp
Nayuki's library requires C++11, and is portable without needing Autotools. Sample usage:
Nayuki 的库需要 C++11,并且无需 Autotools 即可移植。示例用法:
#include <string>
#include <vector>
#include "QrCode.hpp"
using namespace qrcodegen;
// Create the QR Code object
QrCode qr = QrCode::encodeText("Hello, world!", QrCode::Ecc::MEDIUM);
// Read the black & white pixels
for (int y = 0; y < qr.size; y++) {
for (int x = 0; x < qr.size; x++) {
int color = qr.getModule(x, y); // 0 for white, 1 for black
// You need to modify this part
draw_pixel_onto_QT(x, y, color);
}
}
[0]: Fukuchi: 20 files, ~7200 lines among the main .c and .h files (excluding build and test code).
[1]: Nayuki: 6 files, ~1400 lines among the main .cpp and .hpp files (excluding demo code).
[0]:Fukuchi:20 个文件,主 .c 和 .h 文件中的约 7200 行(不包括构建和测试代码)。
[1]:Nayuki:6 个文件,主 .cpp 和 .hpp 文件中约 1400 行(不包括演示代码)。
EDIT 2016-12-08 by OPI decided, with permission, to add my own adaption to Qt. This code compiles and runs fine on my system, And I think it should be independent enough to work elsewhere without too many tweaks as well.
OP 编辑 2016-12-08 经许可,我决定将我自己的改编添加到 Qt。这段代码在我的系统上编译并运行良好,而且我认为它应该足够独立,可以在其他地方工作而无需进行太多调整。
#include "QrCode.hpp"
void paintQR(QPainter &painter, const QSize sz, const QString &data, QColor fg)
{
// NOTE: At this point you will use the API to get the encoding and format you want, instead of my hardcoded stuff:
qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(data.toUtf8().constData(), qrcodegen::QrCode::Ecc::LOW);
const int s=qr.getSize()>0?qr.getSize():1;
const double w=sz.width();
const double h=sz.height();
const double aspect=w/h;
const double size=((aspect>1.0)?h:w);
const double scale=size/(s+2);
// NOTE: For performance reasons my implementation only draws the foreground parts in supplied color.
// It expects background to be prepared already (in white or whatever is preferred).
painter.setPen(Qt::NoPen);
painter.setBrush(fg);
for(int y=0; y<s; y++) {
for(int x=0; x<s; x++) {
const int color=qr.getModule(x, y); // 0 for white, 1 for black
if(0!=color) {
const double rx1=(x+1)*scale, ry1=(y+1)*scale;
QRectF r(rx1, ry1, scale, scale);
painter.drawRects(&r,1);
}
}
}
}
For usage, please see this painterclass.
有关用法,请参阅此画家课程。
回答by Lennart Rolland
UPDATE 3/3-2016:It has come to my attention that there is a small library project that does what my answer does but in a more "prepackaged" way. You can check it out here.
2016 年 3 月 3 日更新:我注意到有一个小型图书馆项目可以完成我的答案所做的工作,但以一种更加“预先打包”的方式。你可以在这里查看。
QR in Qt
Qt中的二维码
There is a small QR-code generator library in pure C and without dependencies, called libqrencode.
有一个用纯 C 编写且没有依赖项的小型 QR 码生成器库,称为libqrencode。
Step 1: Install
第 1 步:安装
Before you can use it, you will have to install it. On my Ubuntu 13.10 that meant typing the following in a shell:
在使用它之前,您必须先安装它。在我的 Ubuntu 13.10 上,这意味着在 shell 中输入以下内容:
sudo aptitude install libqrencode-dev
On other platforms you may have to build it from source by yourself. Simply download the tarball and follow the instructions from the source code download.
在其他平台上,您可能必须自己从源代码构建它。只需下载 tarball 并按照源代码下载中的说明进行操作。
Step 2: Project file
第 2 步:项目文件
Next, you will have to add the library to your project. In my Qt5.2.0 project file (myproject.pro or similar) that meant appending the following line:
接下来,您必须将库添加到您的项目中。在我的 Qt5.2.0 项目文件(myproject.pro 或类似文件)中,这意味着附加以下行:
LIBS += -lqrencode
This should be similar for most versions of Qt that I know.
对于我知道的大多数 Qt 版本,这应该是相似的。
Step 3: encode
第 3 步:编码
Next one must write the code that actually uses the library to encode some input string to QR format. That is one line of code:
接下来必须编写实际使用库将一些输入字符串编码为 QR 格式的代码。那是一行代码:
QRcode *qr=QRcode_encodeString("my string", 1, QR_ECLEVEL_L, QR_MODE_8,0);
NOTE:After experimenting with the parameters I have passed to this function, I have learned that one needs to be careful. Some combinations of parameters failed for no good reason. For example passing 0 as version or using QR_MODE_AN failed with "Invalid parameters". This might be bugs in the ancient version of the library that I am using You have been warned.
注意:在试验了我传递给这个函数的参数后,我了解到需要小心。某些参数组合无缘无故失败。例如,将 0 作为版本传递或使用 QR_MODE_AN 失败并显示“无效参数”。这可能是我正在使用的旧版本库中的错误,您已被警告。
Step 4: render image
第 4 步:渲染图像
Finally, before cleaning up, you need to convert the output to bitmap so that it can be rendered on the screen. This is simpler than it sounds. Instead of listing a bunch of assumptions I will instead included my complete working minimalistic QRWidget implementation here. The interesting bits are in the overridden paintEvent() method.
最后,在清理之前,您需要将输出转换为位图,以便在屏幕上呈现。这比听起来简单。我不会列出一堆假设,而是在这里包含我完整的工作简约 QRWidget 实现。有趣的部分在重写的paintEvent() 方法中。
QRWidget.hpp
QRWidget.hpp
#ifndef QRWIDGET_HPP
#define QRWIDGET_HPP
#include <QWidget>
class QRWidget : public QWidget{
Q_OBJECT
private:
QString data;
public:
explicit QRWidget(QWidget *parent = 0);
void setQRData(QString data);
protected:
void paintEvent(QPaintEvent *);
};
#endif // QRWIDGET_HPP
QRWidget.cpp
QRWidget.cpp
#include "QRWidget.hpp"
#include <QPainter>
#include <QDebug>
#include <qrencode.h>
QRWidget::QRWidget(QWidget *parent) :
QWidget(parent),
data("Hello QR")//Note: The encoding fails with empty string so I just default to something else. Use the setQRData() call to change this.
{
}
void QRWidget::setQRData(QString data){
this->data=data;
update();
}
void QRWidget::paintEvent(QPaintEvent *pe){
QPainter painter(this);
//NOTE: I have hardcoded some parameters here that would make more sense as variables.
QRcode *qr = QRcode_encodeString(data.toStdString().c_str(), 1, QR_ECLEVEL_L, QR_MODE_8, 0);
if(0!=qr){
QColor fg("black");
QColor bg("white");
painter.setBrush(bg);
painter.setPen(Qt::NoPen);
painter.drawRect(0,0,width(),height());
painter.setBrush(fg);
const int s=qr->width>0?qr->width:1;
const double w=width();
const double h=height();
const double aspect=w/h;
const double scale=((aspect>1.0)?h:w)/s;
for(int y=0;y<s;y++){
const int yy=y*s;
for(int x=0;x<s;x++){
const int xx=yy+x;
const unsigned char b=qr->data[xx];
if(b &0x01){
const double rx1=x*scale, ry1=y*scale;
QRectF r(rx1, ry1, scale, scale);
painter.drawRects(&r,1);
}
}
}
QRcode_free(qr);
}
else{
QColor error("red");
painter.setBrush(error);
painter.drawRect(0,0,width(),height());
qDebug()<<"QR FAIL: "<< strerror(errno);
}
qr=0;
}
SummaryIn this little post I have summarized my experience with getting a QR code generator working with Qt.
总结在这篇小博文中,我总结了使用 Qt 使用 QR 代码生成器的经验。