前言

從現在來看 ,QR Code 的使用算是很普遍 , 例如用來產生網頁文章的超連結 、Bitcoin 的位址等等 。 不管目的是什麼 , 產生 QR Code 已經是常有的需求 。 本文山姆鍋分享如何使用 Python 的 qrcode 套件來產生 PySide 可以顯示的 QR Code 圖檔 。

使用的程式庫

本文範例將使用到下列程式庫及其版本編號 :

  • qrcode - 版本 :5.1
  • PySide - 版本 :1.2.2
  • Pillow - 版本 :2.9.0

相依性需求

PySide 需要在執行的電腦上安裝 QT 4 的圖形介面程式庫 , 相關安裝方式可以參考 PySide 文件

產收 QR Code 圖檔

qrcode 是一個給 Python 程式用來產生 QR Code 的程式庫套件 , 最簡單地使用方法 , 只需要如下面範例 :

import qrcode
img = qrcode.make('Some data here')

qrcode 會自動根據資料量來決定產生的 QR Code 版本以及其他參數 。 如果要多一點的控制 , 下面的例子 , 也足夠應用 :

import qrcode
qr = qrcode.QRCode(
    version=1,
    error_correction=qrcode.constants.ERROR_CORRECT_L,
    box_size=10,
    border=4,
)
qr.add_data('Some data')
qr.make(fit=True)

img = qr.make_image()

只要安裝好 qrcode 以及其相依套件 Pillow, 產生 QR Code 可說相對簡單許多 。 如果想要在 PySide 的圖形介面顯示 , 則需要額外的步驟 。 雖然 Pillow 支援多種圖檔輸出格式 , 可以輸出圖檔然後再由 PySide 讀取後顯示 。 但這種作法顯然有點多此一舉 , 且影響效能 ; 最好是將圖檔資料直接交由 PySide 來輸出 。 由於 PySide 不了解 Pillow 的內部格式 , 所以 , 需要將 Pillow 的圖檔資料轉換成 PySide 可以理解的格式 。 基於這個需求 , 山姆鍋寫了兩個公用函式 , 作為產生以及轉換圖檔的用途 。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals

import qrcode
from PySide.QtGui import *


def generate_qrcode_pilimage(data, version=2, box_size=4, border=2):
    """ Generates a QR Code in PIL image.

    :param data:
    :param version:
    :param box_size:
    :param border:
    :return:
    """
    qr = qrcode.QRCode(
        version=version,
        error_correction=qrcode.constants.ERROR_CORRECT_M,
        box_size=box_size,
        border=border,
    )

    qr.add_data(data)
    qr.make(fit=True)

    img = qr.make_image()
    return img


def generate_qrcode_qpixmap(data, version=2, box_size=4, border=2):
    """ Generates a QR Code in QPixmap format.

    :param data: the data to be encoded.
    :param version:
    :param box_size:
    :param border:
    :return: the QPixmap
    """
    img = generate_qrcode_pilimage(data, version, box_size, border)
    img_data = img.convert("RGBA").tostring('raw', 'RGBA')  # 1

    image = QImage(img_data, img.size[0], img.size[1], QImage.Format_ARGB32)
    pix = QPixmap.fromImage(image) # 2
    return pix

上方程式片段共定義兩個函式 ,generate_qrcode_pilimage 以及 ` generate_qrcode_qpixmap` 。 generate_qrcode_pilimage 函式根據 要編碼的資料產生 QR Code 對應的 Pillow 圖檔資料 ;generate_qrcode_qpixmap 則是利用它來將 Pillow 圖檔資料轉換成 PySide 可以顯示 的 QPixmap 物件 。 標號 1 的敘述在將 PIL image 轉換成 PySide ( 其實是 QT4) 可以理解的格式 ; 標號 2 將圖檔資料轉成 QPixmap 物件 , 可透過 QLabel 顯示圖檔 。

顯示 QR Code 圖檔

例如下列程式片段 , 使用上述的函式在對話框中來顯示一個 URL 的 QR Code:

# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals

from PySide.QtCore import *
from PySide.QtGui import *

from ava.util import qrcode_gen


class QRCodeLink(QDialog):
    """ Displays a URL in QR Code image.
    """
    def __init__(self, url, parent=None):
        super(QRCodeLink, self).__init__(parent)
        self.url = url

        image_lbl = QLabel()
        image_lbl.setPixmap(qrcode_gen.generate_qrcode_qpixmap(self.url))

結語

山姆鍋大多數寫過的程式 , 需要使用 QR Code 的場合都只是用來顯示簡單的資料 , 如 URL 網址 、 秘鑰 (secret key) 等 。 雖然可以要求使用者抄寫下來 , 但透過 QR Code 來傳遞到其他裝置可說是友善許多 。 山姆鍋多年前還用 J2ME 寫過自己的 QR Code 掃描程式 , 不過這是題外話了 !