C++ wxWidgets Display and Generate Qr Code

How can I setup and display a custom QR Code in wxWidgets, to encode and display a string?

(Self answered, feel free to contribute better answers)

1 Answer

Using the wxImagePanel example, and the nayuki/QR-Code-generator C++ library, you can pass a string and scale and the QR Code will generate and show.

The files created are:

wxImagePanel.hpp
wxImagePanel.cpp
wxQRCode.hpp
wxQRCode.cpp

First is my cut down wxImagePanel, a widget which lets you set and display images on a rectangular surface:

// wxImagePanel.hpp

#include <wx/wx.h>

class wxImagePanel : public wxPanel {
    private:
        wxBitmap image;
        void updateSize();

    public:
        wxImagePanel(wxFrame *parent, wxBitmap bitmap);
        wxImagePanel(wxFrame *parent);
        void paintNow();
        void paintEvent(wxPaintEvent &evt);
        void render(wxDC &dc);
        void setBitmap(wxBitmap bitmap);

        DECLARE_EVENT_TABLE()
};
// wxImagePanel.cpp

#include "wxImagePanel.hpp"

BEGIN_EVENT_TABLE(wxImagePanel, wxPanel)
EVT_PAINT(wxImagePanel::paintEvent)
END_EVENT_TABLE()

wxImagePanel::wxImagePanel(wxFrame *parent, wxBitmap bitmap): wxPanel(parent), image(bitmap) 
{
    updateSize();
};

wxImagePanel::wxImagePanel(wxFrame *parent): wxPanel(parent) {};

void wxImagePanel::updateSize() 
{
    SetMinSize(wxSize(image.GetWidth(), image.GetHeight()));
}

void wxImagePanel::paintEvent(wxPaintEvent &evt)
{
    wxPaintDC dc(this);
    render(dc);
}

void wxImagePanel::render(wxDC &dc) {
    int x = (GetSize().GetWidth() - image.GetWidth()) / 2;
    int y = (GetSize().GetHeight() - image.GetHeight()) / 2;
    dc.DrawBitmap(image, x, y, false);
}

void wxImagePanel::paintNow() {
    wxClientDC dc(this);
    render(dc);
}

void wxImagePanel::setBitmap(wxBitmap bitmap) {
    image = bitmap;
    updateSize();
    paintNow();
}

Then a QR Code class which subclasses the wxImagePanel and shows the code:

// wxQRCode.hpp

#include "wxImagePanel.hpp"
#include <string>

class wxQRCode : public wxImagePanel 
{
    public:
        wxQRCode(wxFrame *parent, std::string text, unsigned int scale);
        void setText(std::string text);
        void setScale(int scale);
        int getQRSize();

    private:
        void generateQRBitmap();
        std::string qrText;
        unsigned int bitmapScale;
};
// wxQRCode.cpp

#include "wxQRCode.hpp"
#include "QrCode.hpp" // qr code lib
using namespace qrcodegen;

wxQRCode::wxQRCode(wxFrame *parent, std::string text, unsigned int scale)
    : wxImagePanel(parent), qrText(text), bitmapScale(scale)
{
    generateQRBitmap();
};

int wxQRCode::getQRSize()
{
    QrCode qr = QrCode::encodeText(qrText.c_str(), QrCode::Ecc::LOW);
    return qr.getSize();
}

void wxQRCode::generateQRBitmap() 
{
    QrCode qr = QrCode::encodeText(qrText.c_str(), QrCode::Ecc::LOW);
    const int scale = bitmapScale;
    const int size = qr.getSize() * scale;
    const int byteWidth = (size + 7) / 8;
    char bitsChar[size*byteWidth];

    for (int y=0; y<size; y++) {
        for (int xByte=0; xByte<byteWidth; xByte++) {
            char bitChar = 0x00;
            if (qrText != "") { for (int xBit=0; xBit<8; xBit++) {
                    int x = xByte*8 + xBit;
                    int xModule = x / scale;
                    int yModule = y / scale;
                    bool black = qr.getModule(xModule, yModule);
                    bitChar += black << (xBit % 8);
                }}
            bitsChar[y * byteWidth + xByte] = bitChar;
        }
    }
    
    wxBitmap *bitmap = new wxBitmap(bitsChar, size, size, 1);
    setBitmap(*bitmap);
};

void wxQRCode::setText(std::string text) {
    qrText = text;
    if (text != "") {
        Show(true);
        generateQRBitmap();
        paintNow();
    } else {
        Show(false);
    }
};

void wxQRCode::setScale(int scale) {
    bitmapScale = scale;
    generateQRBitmap();
    paintNow();
};

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Robert Thorne

Robert Thorne

Automotive & Future Transportation Editor

Robert Thorne covers electric vehicle innovations, autonomous driving systems, global mobility trends, and automotive engineering developments.

Share this article
Twitter Facebook Pinterest