1. 程式人生 > >Qt專案實戰3:二維碼生成器

Qt專案實戰3:二維碼生成器

qrtool專案簡介

二維碼(Qrcode)現在越來越常用,掃碼支付、掃碼新增好友、掃碼乘坐公交車和地鐵,我們的生活已經與二維碼息息相關。這裡我們使用qt軟體+qrencode開源庫來生成、顯示、儲存二維碼圖片,並且支援簡單的二維碼容錯率修改和大小修改。 ui效果圖如下: ui

qrencode開源庫

libqrencode 是生成二維碼資料的開源庫。 github連結 。 在Windows平臺,使用CMake工具構建libqrencode工程,生成靜態庫,在qt工程中使用。

構建qrencode工程

安裝cmake工具 官網下載連結。 使用cmake構建工程 cmake 修改工程配置資訊: 在這裡插入圖片描述 這裡需要注意的是,構建qrencode庫,不關聯iconv和libpng庫。 使用Configure命令生成工程配置檔案,使用Generate命令生成Makefile檔案,構建完成。

編譯libqrencode庫

構建完成後,進入命令列,進行編譯:

Microsoft Windows [版本 10.0.17134.228]
(c) 2018 Microsoft Corporation。保留所有權利。

C:\Users\Administrator> cd /d E:\opensource\libqrencode-master\build

E:\opensource\libqrencode-master\build>mingw32-make
-- Could NOT find ZLIB (missing: ZLIB_LIBRARY ZLIB_INCLUDE_DIR)
-- Could NOT find
PNG (missing: PNG_LIBRARY PNG_PNG_INCLUDE_DIR) -- Could NOT find ICONV (missing: ICONV_FOUND_ANY ICONV_INCLUDE_DIR) -- ------------------------------------------------------------ -- [QRencode] Configuration summary. -- ------------------------------------------------------------ -- System configuration: -- ..
Processor type .............. = AMD64 -- .. CMake executable ............ = D:/Program Files/CMake/bin/cmake.exe -- .. CMake version ............... = 3.12.1 -- .. System name ................. = Windows-10.0.17134 -- .. C++ compiler ................ = -- .. C compiler .................. = D:/software/Qt/Qt5.6.0/Tools/mingw492_32/bin/gcc.exe -- .. size(void*) ................. = 4 -- Dependencies: -- .. Thread library of the system = -- .. Iconv ....................... = FALSE -- .... Iconv includes ............ = ICONV_INCLUDE_DIR-NOTFOUND -- .... Iconv library ............. = ICONV_LIBRARY-NOTFOUND -- .. ZLIB ........................ = FALSE -- .. PNG ......................... = FALSE -- .... PNG includes .............. = -- .... PNG library ............... = -- Project configuration: -- .. Build test programs ........ = OFF -- .. Build utility tools ........ = OFF -- .. Disable PNG support ........ = OFF -- .. Installation prefix ......... = E:/opensource/libqrencode-master/install -- ------------------------------------------------------------ -- Configuring done -- Generating done -- Build files have been written to: E:/opensource/libqrencode-master/build Scanning dependencies of target qrencode [ 10%] Building C object CMakeFiles/qrencode.dir/qrencode.c.obj [ 20%] Building C object CMakeFiles/qrencode.dir/qrinput.c.obj [ 30%] Building C object CMakeFiles/qrencode.dir/bitstream.c.obj [ 40%] Building C object CMakeFiles/qrencode.dir/qrspec.c.obj [ 50%] Building C object CMakeFiles/qrencode.dir/rsecc.c.obj [ 60%] Building C object CMakeFiles/qrencode.dir/split.c.obj [ 70%] Building C object CMakeFiles/qrencode.dir/mask.c.obj [ 80%] Building C object CMakeFiles/qrencode.dir/mqrspec.c.obj [ 90%] Building C object CMakeFiles/qrencode.dir/mmask.c.obj [100%] Linking C static library libqrencode.a [100%] Built target qrencode E:\opensource\libqrencode-master\build>mingw32-make install [100%] Built target qrencode Install the project... -- Install configuration: "" -- Up-to-date: E:/opensource/libqrencode-master/install/share/man/man1/qrencode.1 -- Up-to-date: E:/opensource/libqrencode-master/install/lib/pkgconfig/libqrencode.pc -- Up-to-date: E:/opensource/libqrencode-master/install/include/qrencode.h -- Installing: E:/opensource/libqrencode-master/install/lib/libqrencode.a E:\opensource\libqrencode-master\build>

使用mingw32-makemingw32-make install命令編譯和安裝庫檔案。安裝完成後,將生成的libqrencode庫拷貝到qt工程中以供使用。

生成二維碼資料

使用QRcode_encodeString函式來生成二維碼資料,函式原型如下:

QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)

引數string表示需要轉換的資料,QRecLevel和QRencodeMode列舉型別如下所示。casesensitive表示是否使能大小寫敏感,預設啟用就可以了。

/**
 * Level of error correction.
 */
typedef enum {
	QR_ECLEVEL_L = 0, ///< lowest
	QR_ECLEVEL_M,
	QR_ECLEVEL_Q,
	QR_ECLEVEL_H      ///< highest
} QRecLevel;

/**
 * Encoding mode.
 */
typedef enum {
	QR_MODE_NUL = -1,   ///< Terminator (NUL character). Internal use only
	QR_MODE_NUM = 0,    ///< Numeric mode
	QR_MODE_AN,         ///< Alphabet-numeric mode
	QR_MODE_8,          ///< 8-bit data mode
	QR_MODE_KANJI,      ///< Kanji (shift-jis) mode
	QR_MODE_STRUCTURE,  ///< Internal use only
	QR_MODE_ECI,        ///< ECI mode
	QR_MODE_FNC1FIRST,  ///< FNC1, first position
	QR_MODE_FNC1SECOND, ///< FNC1, second position
} QRencodeMode;

encode成功後,返回QRcode結構體資料:

/**
 * QRcode class.
 * Symbol data is represented as an array contains width*width uchars.
 * Each uchar represents a module (dot). If the less significant bit of
 * the uchar is 1, the corresponding module is black. The other bits are
 * meaningless for usual applications, but here its specification is described.
 *
 * @verbatim
   MSB 76543210 LSB
       |||||||`- 1=black/0=white
       ||||||`-- 1=ecc/0=data code area
       |||||`--- format information
       ||||`---- version information
       |||`----- timing pattern
       ||`------ alignment pattern
       |`------- finder pattern and separator
       `-------- non-data modules (format, timing, etc.)
   @endverbatim
 */
typedef struct {
	int version;         ///< version of the symbol
	int width;           ///< width of the symbol
	unsigned char *data; ///< symbol data
} QRcode;

使用encode轉換的data和width資料,即可繪製出二維碼圖片。

繪製二維碼圖片

在Qt中,使用QImage類來建立一個圖片例項,使用QPainter類來繪製圖片。 繪製圖片步驟:

  • 建立QPainter例項,在已經存在的image例項上繪製
  • 建立一張空白的畫布
  • 使用黑色畫刷,根據資料寬度畫畫素矩形
  • 將二維碼生成的資料填充在畫布上
void Widget::genQrcodeImage(char *qr_str, int width, int height)
{
    QRcode *qrcode = NULL;

    if (qr_str == NULL || width <= 0 || height <= 0)
        return ;

    qrcode = QRcode_encodeString(qr_str, qrcode_version, QR_ECLEVEL_M, QR_MODE_8, 1);
    if(qrcode != NULL) {
        QPainter painter(image);
        unsigned char *point = qrcode->data;
        painter.setPen(Qt::NoPen);
        painter.setBrush(Qt::white);
        painter.drawRect(0, 0, width, height);
        double scale = (width - 2.0 * margin) / qrcode->width;
        painter.setBrush(Qt::black);
        for (int y = 0; y < qrcode->width; y++) {
            for (int x = 0; x < qrcode->width; x++) {
                if (*point & 1) {
                    QRectF r(margin + x * scale, margin + y * scale, scale, scale);
                    painter.drawRects(&r, 1);
                }
                point++;
            }
        }
        point = NULL;
        QRcode_free(qrcode);
        qrcode = NULL;
    }
}

繪製完成後,在QLabel上顯示圖片:

QPixmap pixmap = QPixmap::fromImage(*image);
ui->qrLabel->setPixmap(pixmap);