如何在本机C / C ++中用Qt绘制二维码

问题描述 投票:23回答:2

QR中的Qt

作为How to scan for QR codes with Qt的伴侣问题,我想知道如何在我的基于Qt5的桌面应用程序中从本机C / C ++代码中绘制QR code,但我找不到如何执行此操作的示例。

我知道QtQR存在,但它依赖于python-qrtools,在我看来这种方式首先打败了使用Qt的目的。我想要一个灵活,高效且无依赖的解决方案,无论我决定采用哪种解决方案,都可以使用我的应用程序进行编译。

我怎样才能做到这一点?

c++ qt render qr-code
2个回答
8
投票

如果您认为Fukuchi的库太大[0],请考虑查看Nayuki的C ++ QR Code生成器库[1]:https://github.com/nayuki/QR-Code-generator/tree/master/cpp

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个文件,主要.c和.h文件中的~7200行(不包括构建和测试代码)。 [1]:Nayuki:6个文件,主要.cpp和.hpp文件中的约1400行(不包括演示代码)。


由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);
            }
        }
    }
}

如需使用,请参阅此painter课程。


30
投票

更新3 / 3-2016:我注意到有一个小型的图书馆项目可以做到我的答案,但是采用了更加“预先包装”的方式。你可以看看here

QR中的Qt

在纯C中有一个小的QR码生成器库,没有依赖关系,称为libqrencode

第1步:安装

在使用它之前,您必须安装它。在我的Ubuntu 13.10上,这意味着在shell中键入以下内容:

sudo aptitude install libqrencode-dev

在其他平台上,您可能需要自己从源代码构建它。只需下载tarball并按照source code download的说明操作即可。

第2步:项目文件

接下来,您必须将库添加到项目中。在我的Qt5.2.0项目文件(myproject.pro或类似文件)中,这意味着附加以下行:

LIBS += -lqrencode

对于我所知道的大多数Qt版本,这应该是类似的。

第3步:编码

接下来必须编写实际使用库的代码,将某些输入字符串编码为QR格式。这是一行代码:

QRcode *qr=QRcode_encodeString("my string", 1, QR_ECLEVEL_L, QR_MODE_8,0);

注意:在尝试了我传递给这个函数的参数之后,我了解到需要小心。一些参数组合失败没有充分的理由。例如,将0作为版本传递或使用QR_MODE_AN失败并显示“无效参数”。这可能是我正在使用的古代版本库中的错误你已被警告过。

第4步:渲染图像

最后,在清理之前,您需要将输出转换为位图,以便可以在屏幕上呈现。这比听起来简单。我没有列出一堆假设,而是在这里包含了我完整的工作简约QRWidget实现。有趣的位在重写的paintEvent()方法中。

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

#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;
}

总结在这篇小文章中,我总结了我使用Qt的QR代码生成器的经验。

© www.soinside.com 2019 - 2024. All rights reserved.