使用 Python 生成二维条形码 QR Codes

SerenaClary 8年前

前几天,我估摸着做一个能生成QR Code小程序,并能用wxPython在屏幕上显示出来。当然,我想用纯Python实现,观望了一会后,我找到了三个候选:

我尝试了python-qrcode以及pyqrnative,因为它们能够运行在Windows/Mac/Linux。也不需要依赖额外的其他库除了Python图像库。pyqrcode项目需要其他一些先决条件,并且不能在Windows上运行,所以我不想与之纠缠了。我最后使用了一些以前写过的一个Photo Viewer程序的代码,然后稍微地修改了一下,就成了QRCode的查看器了。

开始

正如我上面提到的,你只需要Python图像库,GUI部分我们将使用wxPython。python-qrcode相比pyqrnative生成图片更快,并包含了你见过的大多数QR码类型。

生成 QR Codes

当你准备好所有需要的以后,你可以运行以下代码,看看Python做了些啥:

import os import wx

try: import qrcode except ImportError: qrcode = None

try: import PyQRNative except ImportError: PyQRNative = None

class QRPanel(wx.Panel): """"""

#----------------------------------------------------------------------  def __init__(self, parent):      """Constructor"""      wx.Panel.__init__(self, parent=parent)      self.photo_max_size = 240      sp = wx.StandardPaths.Get()      self.defaultLocation = sp.GetDocumentsDir()        img = wx.EmptyImage(240,240)      self.imageCtrl = wx.StaticBitmap(self, wx.ID_ANY,                                       wx.BitmapFromImage(img))        qrDataLbl = wx.StaticText(self, label="Text to turn into QR Code:")      self.qrDataTxt = wx.TextCtrl(self, value="http://www.mousevspython.com", size=(200,-1))      instructions = "Name QR image file"      instructLbl = wx.StaticText(self, label=instructions)      self.qrPhotoTxt = wx.TextCtrl(self, size=(200,-1))      browseBtn = wx.Button(self, label='Change Save Location')      browseBtn.Bind(wx.EVT_BUTTON, self.onBrowse)      defLbl = "Default save location: " + self.defaultLocation      self.defaultLocationLbl = wx.StaticText(self, label=defLbl)        qrcodeBtn = wx.Button(self, label="Create QR with qrcode")      qrcodeBtn.Bind(wx.EVT_BUTTON, self.onUseQrcode)      pyQRNativeBtn = wx.Button(self, label="Create QR with PyQRNative")      pyQRNativeBtn.Bind(wx.EVT_BUTTON, self.onUsePyQR)        # Create sizer      self.mainSizer = wx.BoxSizer(wx.VERTICAL)      qrDataSizer = wx.BoxSizer(wx.HORIZONTAL)      locationSizer = wx.BoxSizer(wx.HORIZONTAL)      qrBtnSizer = wx.BoxSizer(wx.VERTICAL)        qrDataSizer.Add(qrDataLbl, 0, wx.ALL, 5)      qrDataSizer.Add(self.qrDataTxt, 1, wx.ALL|wx.EXPAND, 5)      self.mainSizer.Add(wx.StaticLine(self, wx.ID_ANY),                         0, wx.ALL|wx.EXPAND, 5)      self.mainSizer.Add(qrDataSizer, 0, wx.EXPAND)      self.mainSizer.Add(self.imageCtrl, 0, wx.ALL, 5)      locationSizer.Add(instructLbl, 0, wx.ALL, 5)      locationSizer.Add(self.qrPhotoTxt, 0, wx.ALL, 5)      locationSizer.Add(browseBtn, 0, wx.ALL, 5)      self.mainSizer.Add(locationSizer, 0, wx.ALL, 5)      self.mainSizer.Add(self.defaultLocationLbl, 0, wx.ALL, 5)        qrBtnSizer.Add(qrcodeBtn, 0, wx.ALL, 5)      qrBtnSizer.Add(pyQRNativeBtn, 0, wx.ALL, 5)      self.mainSizer.Add(qrBtnSizer, 0, wx.ALL|wx.CENTER, 10)        self.SetSizer(self.mainSizer)      self.Layout()    #----------------------------------------------------------------------  def onBrowse(self, event):      """"""      dlg = wx.DirDialog(self, "Choose a directory:",                         style=wx.DD_DEFAULT_STYLE)      if dlg.ShowModal() == wx.ID_OK:          path = dlg.GetPath()          self.defaultLocation = path          self.defaultLocationLbl.SetLabel("Save location: %s" % path)      dlg.Destroy()    #----------------------------------------------------------------------  def onUseQrcode(self, event):      """

https://github.com/lincolnloop/python-qrcode

"""      qr = qrcode.QRCode(version=1, box_size=10, border=4)      qr.add_data(self.qrDataTxt.GetValue())      qr.make(fit=True)      x = qr.make_image()        qr_file = os.path.join(self.defaultLocation, self.qrPhotoTxt.GetValue() + ".jpg")      img_file = open(qr_file, 'wb')      x.save(img_file, 'JPEG')      img_file.close()      self.showQRCode(qr_file)    #----------------------------------------------------------------------  def onUsePyQR(self, event):      """

http://code.google.com/p/pyqrnative/

"""      qr = PyQRNative.QRCode(20, PyQRNative.QRErrorCorrectLevel.L)      qr.addData(self.qrDataTxt.GetValue())      qr.make()      im = qr.makeImage()        qr_file = os.path.join(self.defaultLocation, self.qrPhotoTxt.GetValue() + ".jpg")      img_file = open(qr_file, 'wb')      im.save(img_file, 'JPEG')      img_file.close()      self.showQRCode(qr_file)    #----------------------------------------------------------------------  def showQRCode(self, filepath):      """"""      img = wx.Image(filepath, wx.BITMAP_TYPE_ANY)      # scale the image, preserving the aspect ratio      W = img.GetWidth()      H = img.GetHeight()      if W > H:          NewW = self.photo_max_size          NewH = self.photo_max_size * H / W      else:          NewH = self.photo_max_size          NewW = self.photo_max_size * W / H      img = img.Scale(NewW,NewH)        self.imageCtrl.SetBitmap(wx.BitmapFromImage(img))      self.Refresh()

class QRFrame(wx.Frame): """"""

#----------------------------------------------------------------------  def __init__(self):      """Constructor"""      wx.Frame.__init__(self, None, title="QR Code Viewer", size=(550,500))      panel = QRPanel(self)

if name == " main ": app = wx.App(False) frame = QRFrame() frame.Show() app.MainLoop()

importos  importwx     try:      importqrcode  exceptImportError:      qrcode = None     try:      importPyQRNative  exceptImportError:      PyQRNative = None     ########################################################################  class QRPanel(wx.Panel):      """"""         #----------------------------------------------------------------------      def__init__(self, parent):          """Constructor"""          wx.Panel.__init__(self, parent=parent)          self.photo_max_size = 240          sp = wx.StandardPaths.Get()          self.defaultLocation = sp.GetDocumentsDir()             img = wx.EmptyImage(240,240)          self.imageCtrl = wx.StaticBitmap(self, wx.ID_ANY,                                          wx.BitmapFromImage(img))             qrDataLbl = wx.StaticText(self, label="Text to turn into QR Code:")          self.qrDataTxt = wx.TextCtrl(self, value="http://www.mousevspython.com", size=(200,-1))          instructions = "Name QR image file"          instructLbl = wx.StaticText(self, label=instructions)          self.qrPhotoTxt = wx.TextCtrl(self, size=(200,-1))          browseBtn = wx.Button(self, label='Change Save Location')          browseBtn.Bind(wx.EVT_BUTTON, self.onBrowse)          defLbl = "Default save location: " + self.defaultLocation          self.defaultLocationLbl = wx.StaticText(self, label=defLbl)             qrcodeBtn = wx.Button(self, label="Create QR with qrcode")          qrcodeBtn.Bind(wx.EVT_BUTTON, self.onUseQrcode)          pyQRNativeBtn = wx.Button(self, label="Create QR with PyQRNative")          pyQRNativeBtn.Bind(wx.EVT_BUTTON, self.onUsePyQR)             # Create sizer          self.mainSizer = wx.BoxSizer(wx.VERTICAL)          qrDataSizer = wx.BoxSizer(wx.HORIZONTAL)          locationSizer = wx.BoxSizer(wx.HORIZONTAL)          qrBtnSizer = wx.BoxSizer(wx.VERTICAL)             qrDataSizer.Add(qrDataLbl, 0, wx.ALL, 5)          qrDataSizer.Add(self.qrDataTxt, 1, wx.ALL|wx.EXPAND, 5)          self.mainSizer.Add(wx.StaticLine(self, wx.ID_ANY),                            0, wx.ALL|wx.EXPAND, 5)          self.mainSizer.Add(qrDataSizer, 0, wx.EXPAND)          self.mainSizer.Add(self.imageCtrl, 0, wx.ALL, 5)          locationSizer.Add(instructLbl, 0, wx.ALL, 5)          locationSizer.Add(self.qrPhotoTxt, 0, wx.ALL, 5)          locationSizer.Add(browseBtn, 0, wx.ALL, 5)          self.mainSizer.Add(locationSizer, 0, wx.ALL, 5)          self.mainSizer.Add(self.defaultLocationLbl, 0, wx.ALL, 5)             qrBtnSizer.Add(qrcodeBtn, 0, wx.ALL, 5)          qrBtnSizer.Add(pyQRNativeBtn, 0, wx.ALL, 5)          self.mainSizer.Add(qrBtnSizer, 0, wx.ALL|wx.CENTER, 10)             self.SetSizer(self.mainSizer)          self.Layout()         #----------------------------------------------------------------------      defonBrowse(self, event):          """"""          dlg = wx.DirDialog(self, "Choose a directory:",                            style=wx.DD_DEFAULT_STYLE)          if dlg.ShowModal() == wx.ID_OK:              path = dlg.GetPath()              self.defaultLocation = path              self.defaultLocationLbl.SetLabel("Save location: %s" % path)          dlg.Destroy()         #----------------------------------------------------------------------      defonUseQrcode(self, event):          """     https://github.com/lincolnloop/python-qrcode             """          qr = qrcode.QRCode(version=1, box_size=10, border=4)          qr.add_data(self.qrDataTxt.GetValue())          qr.make(fit=True)          x = qr.make_image()             qr_file = os.path.join(self.defaultLocation, self.qrPhotoTxt.GetValue() + ".jpg")          img_file = open(qr_file, 'wb')          x.save(img_file, 'JPEG')          img_file.close()          self.showQRCode(qr_file)         #----------------------------------------------------------------------      defonUsePyQR(self, event):          """     http://code.google.com/p/pyqrnative/             """          qr = PyQRNative.QRCode(20, PyQRNative.QRErrorCorrectLevel.L)          qr.addData(self.qrDataTxt.GetValue())          qr.make()          im = qr.makeImage()             qr_file = os.path.join(self.defaultLocation, self.qrPhotoTxt.GetValue() + ".jpg")          img_file = open(qr_file, 'wb')          im.save(img_file, 'JPEG')          img_file.close()          self.showQRCode(qr_file)         #----------------------------------------------------------------------      defshowQRCode(self, filepath):          """"""          img = wx.Image(filepath, wx.BITMAP_TYPE_ANY)          # scale the image, preserving the aspect ratio          W = img.GetWidth()          H = img.GetHeight()          if W > H:              NewW = self.photo_max_size              NewH = self.photo_max_size * H / W          else:              NewH = self.photo_max_size              NewW = self.photo_max_size * W / H          img = img.Scale(NewW,NewH)             self.imageCtrl.SetBitmap(wx.BitmapFromImage(img))          self.Refresh()     ########################################################################  class QRFrame(wx.Frame):      """"""         #----------------------------------------------------------------------      def__init__(self):          """Constructor"""          wx.Frame.__init__(self, None, title="QR Code Viewer", size=(550,500))          panel = QRPanel(self)     if __name__ == "__main__":      app = wx.App(False)      frame = QRFrame()      frame.Show()      app.MainLoop()
</div>

python-qrcode生成效果图:

PyQRNative生成效果图:

译者注:Java QrCode 生成可选用d-project, 点击查看实例

</div>

来自: http://python.jobbole.com/84192/