Comment dessiner un code QR avec Qt en C/C++natif

QR Qt

comme question complémentaire à comment scanner les codes QR avec Qt , je veux savoir comment dessiner un code QR à partir du code natif C/C++ dans mon application de bureau basée Qt5, mais je n'ai pas pu trouver un exemple de la façon de le faire.

je sais QtQR existe, mais il a des dépendances sur python-qrtools qui à mon avis gentil de défait le but de L'utilisation de Qt en premier lieu. Je veux une solution agile, efficace et sans dépendance qui se compilera avec mon application là où j'ai décidé de l'utiliser.

Comment faire?

23
demandé sur Community 2014-01-28 12:20:13

2 réponses

si vous pensez que la bibliothèque de Fukuchi est trop grande [0] pour vous, pensez à regarder la bibliothèque du générateur de Code C++ QR de Nayuki [1] : https://github.com/nayuki/QR-Code-generator/tree/master/cpp

la bibliothèque de Nayuki nécessite C++11, et est portable sans avoir besoin D'Autotools. Exemple d'utilisation:

#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 fichiers, ~ 7200 lignes parmi les principaux .c et .fichiers h (à l'exclusion du code de construction et de test).

[1]: Nayuki: 6 fichiers, ~1400 lignes parmi les principaux .rpc et .fichiers hpp (à l'exclusion du code Démo).


modifier le 2016-12-08 par OP J'ai décidé, avec ma permission, d'ajouter ma propre adaptation au Qt. Ce code compile et fonctionne très bien sur mon système, Et je pense qu'il devrait être assez indépendants pour travailler ailleurs sans trop de tweaks.

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

pour l'usage, s'il vous plaît voir ce peintre classe.

8
répondu Nayuki 2017-12-06 01:52:12

mise à jour 3/3-2016: il m'est venu à l'attention qu'il y a un petit projet de bibliothèque qui fait ce que ma réponse fait, mais d'une manière plus" préemballée". Vous pouvez le consulter ici .

QR Qt

il existe une petite bibliothèque génératrice de code QR en C pur et sans dépendances, appelée libqrencode .

Étape 1: Installer

Avant de pouvoir l'utiliser, vous devrez l'installer. Sur mon Ubuntu 13.10 cela signifiait taper ce qui suit dans un shell:

sudo aptitude install libqrencode-dev

sur d'autres plates-formes, vous pouvez avoir à le construire à partir de la source par vous-même. Il suffit de télécharger l'archive et de suivre les instructions du source code download .

Étape 2: Dossier de projet

ensuite, vous devrez ajouter la bibliothèque à votre projet. Dans mon Qt5.2.0 dossier de projet (maproject.pro ou similaire), ce qui signifie ajouter la ligne suivante:

LIBS += -lqrencode

cela devrait être similaire pour la plupart des versions de Qt que je connais.

Étape 3: encoder

le suivant doit écrire le code qui utilise réellement la bibliothèque pour encoder une chaîne de caractères au format QR. C'est une ligne de code:

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

NOTE: après avoir expérimenté les paramètres que j'ai passés à cette fonction, j'ai appris qu'il faut être prudent. Certaines combinaisons de paramètres ont échoué sans raison valable. Par exemple, passer 0 comme version ou utiliser QR_MODE_AN a échoué avec "paramètres invalides". Cela pourrait être des bogues dans la version ancienne de la bibliothèque que J'utilise Vous ont été prévenus.

Étape 4: rendre l'image

enfin, avant de nettoyer, vous devez convertir la sortie en bitmap pour qu'elle puisse être rendue sur l'écran. C'est plus simple qu'il n'y paraît. Au lieu d'énumérer un tas d'hypothèses, je vais plutôt inclure mon travail minimaliste qrwidget implémentation complète ici. Les bits intéressants sont dans la méthode paintEvent overridden ().

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

résumé Dans ce petit billet, j'ai résumé mon expérience avec l'obtention d'un générateur de code QR fonctionnant avec Qt.

30
répondu Lennart Rolland 2016-03-03 14:07:21