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

jerry Python 2015年11月23日 收藏

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

  • github 上的 python-qrcode
  • sourceforge上的 pyqrcode
  • Goolge code 上的 pyqrnative

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

开始

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

生成 QR Codes

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

  1. import os
  2. import wx
  3. try:
  4. import qrcode
  5. except ImportError:
  6. qrcode = None
  7. try:
  8. import PyQRNative
  9. except ImportError:
  10. PyQRNative = None
  11. ########################################################################
  12. class QRPanel(wx.Panel):
  13. """"""
  14. #----------------------------------------------------------------------
  15. def __init__(self, parent):
  16. """Constructor"""
  17. wx.Panel.__init__(self, parent=parent)
  18. self.photo_max_size = 240
  19. sp = wx.StandardPaths.Get()
  20. self.defaultLocation = sp.GetDocumentsDir()
  21. img = wx.EmptyImage(240,240)
  22. self.imageCtrl = wx.StaticBitmap(self, wx.ID_ANY,
  23. wx.BitmapFromImage(img))
  24. qrDataLbl = wx.StaticText(self, label="Text to turn into QR Code:")
  25. self.qrDataTxt = wx.TextCtrl(self, value="http://www.mousevspython.com", size=(200,-1))
  26. instructions = "Name QR image file"
  27. instructLbl = wx.StaticText(self, label=instructions)
  28. self.qrPhotoTxt = wx.TextCtrl(self, size=(200,-1))
  29. browseBtn = wx.Button(self, label='Change Save Location')
  30. browseBtn.Bind(wx.EVT_BUTTON, self.onBrowse)
  31. defLbl = "Default save location: " + self.defaultLocation
  32. self.defaultLocationLbl = wx.StaticText(self, label=defLbl)
  33. qrcodeBtn = wx.Button(self, label="Create QR with qrcode")
  34. qrcodeBtn.Bind(wx.EVT_BUTTON, self.onUseQrcode)
  35. pyQRNativeBtn = wx.Button(self, label="Create QR with PyQRNative")
  36. pyQRNativeBtn.Bind(wx.EVT_BUTTON, self.onUsePyQR)
  37. # Create sizer
  38. self.mainSizer = wx.BoxSizer(wx.VERTICAL)
  39. qrDataSizer = wx.BoxSizer(wx.HORIZONTAL)
  40. locationSizer = wx.BoxSizer(wx.HORIZONTAL)
  41. qrBtnSizer = wx.BoxSizer(wx.VERTICAL)
  42. qrDataSizer.Add(qrDataLbl, 0, wx.ALL, 5)
  43. qrDataSizer.Add(self.qrDataTxt, 1, wx.ALL|wx.EXPAND, 5)
  44. self.mainSizer.Add(wx.StaticLine(self, wx.ID_ANY),
  45. 0, wx.ALL|wx.EXPAND, 5)
  46. self.mainSizer.Add(qrDataSizer, 0, wx.EXPAND)
  47. self.mainSizer.Add(self.imageCtrl, 0, wx.ALL, 5)
  48. locationSizer.Add(instructLbl, 0, wx.ALL, 5)
  49. locationSizer.Add(self.qrPhotoTxt, 0, wx.ALL, 5)
  50. locationSizer.Add(browseBtn, 0, wx.ALL, 5)
  51. self.mainSizer.Add(locationSizer, 0, wx.ALL, 5)
  52. self.mainSizer.Add(self.defaultLocationLbl, 0, wx.ALL, 5)
  53. qrBtnSizer.Add(qrcodeBtn, 0, wx.ALL, 5)
  54. qrBtnSizer.Add(pyQRNativeBtn, 0, wx.ALL, 5)
  55. self.mainSizer.Add(qrBtnSizer, 0, wx.ALL|wx.CENTER, 10)
  56. self.SetSizer(self.mainSizer)
  57. self.Layout()
  58. #----------------------------------------------------------------------
  59. def onBrowse(self, event):
  60. """"""
  61. dlg = wx.DirDialog(self, "Choose a directory:",
  62. style=wx.DD_DEFAULT_STYLE)
  63. if dlg.ShowModal() == wx.ID_OK:
  64. path = dlg.GetPath()
  65. self.defaultLocation = path
  66. self.defaultLocationLbl.SetLabel("Save location: %s" % path)
  67. dlg.Destroy()
  68. #----------------------------------------------------------------------
  69. def onUseQrcode(self, event):
  70. """
  71.  
  72. https://github.com/lincolnloop/python-qrcode
  73.  
  74. """
  75. qr = qrcode.QRCode(version=1, box_size=10, border=4)
  76. qr.add_data(self.qrDataTxt.GetValue())
  77. qr.make(fit=True)
  78. x = qr.make_image()
  79. qr_file = os.path.join(self.defaultLocation, self.qrPhotoTxt.GetValue() + ".jpg")
  80. img_file = open(qr_file, 'wb')
  81. x.save(img_file, 'JPEG')
  82. img_file.close()
  83. self.showQRCode(qr_file)
  84. #----------------------------------------------------------------------
  85. def onUsePyQR(self, event):
  86. """
  87.  
  88. http://code.google.com/p/pyqrnative/
  89.  
  90. """
  91. qr = PyQRNative.QRCode(20, PyQRNative.QRErrorCorrectLevel.L)
  92. qr.addData(self.qrDataTxt.GetValue())
  93. qr.make()
  94. im = qr.makeImage()
  95. qr_file = os.path.join(self.defaultLocation, self.qrPhotoTxt.GetValue() + ".jpg")
  96. img_file = open(qr_file, 'wb')
  97. im.save(img_file, 'JPEG')
  98. img_file.close()
  99. self.showQRCode(qr_file)
  100. #----------------------------------------------------------------------
  101. def showQRCode(self, filepath):
  102. """"""
  103. img = wx.Image(filepath, wx.BITMAP_TYPE_ANY)
  104. # scale the image, preserving the aspect ratio
  105. W = img.GetWidth()
  106. H = img.GetHeight()
  107. if W > H:
  108. NewW = self.photo_max_size
  109. NewH = self.photo_max_size * H / W
  110. else:
  111. NewH = self.photo_max_size
  112. NewW = self.photo_max_size * W / H
  113. img = img.Scale(NewW,NewH)
  114. self.imageCtrl.SetBitmap(wx.BitmapFromImage(img))
  115. self.Refresh()
  116. ########################################################################
  117. class QRFrame(wx.Frame):
  118. """"""
  119. #----------------------------------------------------------------------
  120. def __init__(self):
  121. """Constructor"""
  122. wx.Frame.__init__(self, None, title="QR Code Viewer", size=(550,500))
  123. panel = QRPanel(self)
  124. if __name__ == "__main__":
  125. app = wx.App(False)
  126. frame = QRFrame()
  127. frame.Show()
  128. app.MainLoop()

python-qrcode生成效果图:

PyQRNative生成效果图: