【问题标题】:Create QR-code in Python (PyQt)在 Python (PyQt) 中创建二维码
【发布时间】:2013-12-08 10:45:36
【问题描述】:

我目前正在使用 PyQt4 和 qrcode4.0.4

from PyQt4 import QtGui, QtCore
from PIL.ImageQt import ImageQt
import qrcode

class QRLabel(QtGui.QLabel):
    def __init__(self, text=""):
        super(QRLabel, self).__init__()
        self.setCode(text)

    def setCode(self, text=""):        
        self.text = text      
        qrImg = qrcode.make(text)
        imgQt = ImageQt(qrImg.convert("RGB"))   # keep a reference!
        pixm = QtGui.QPixmap.fromImage(imgQt)
        self.setPixmap(pixm.scaled(self.size(),QtCore.Qt.KeepAspectRatio))

如您所见,在您将图像显示在屏幕上之前,需要克服几个障碍。 QR 码以 RGBA PIL 图像开始,然后转换为 RGB,然后转换为 PIL ImageQt 对象,然后转换为 QPixmap,然后将其放置在具有缩放修复的 QLabel 上。

如果您没有显式存储 imgQt 引用,则在加载小部件时会出现垃圾。

我的问题:我可以做些什么来改进这一点,因为似乎涉及到很多转换。

【问题讨论】:

    标签: python pyqt python-imaging-library qr-code qpixmap


    【解决方案1】:

    从 qrcode 文档看来,您可以创建自己的 image_factory,这可能会让您简化流程。

    您只需要继承qrcode.image.base.BaseImage 并重新实现new_imagedrawrectsave 方法。这个子类可以包装一个 QImage,因此不需要 PIL 转换步骤。

    更新

    这是一个消除 PIL 依赖的演示(这也很好,因为我发现 PIL 在某些输入下会崩溃):

    from PyQt4 import QtGui, QtCore
    import qrcode
    
    class Image(qrcode.image.base.BaseImage):
        def __init__(self, border, width, box_size):
            self.border = border
            self.width = width
            self.box_size = box_size
            size = (width + border * 2) * box_size
            self._image = QtGui.QImage(
                size, size, QtGui.QImage.Format_RGB16)
            self._image.fill(QtCore.Qt.white)
    
        def pixmap(self):
            return QtGui.QPixmap.fromImage(self._image)
    
        def drawrect(self, row, col):
            painter = QtGui.QPainter(self._image)
            painter.fillRect(
                (col + self.border) * self.box_size,
                (row + self.border) * self.box_size,
                self.box_size, self.box_size,
                QtCore.Qt.black)
    
        def save(self, stream, kind=None):
            pass
    
    class Window(QtGui.QWidget):
        def __init__(self):
            QtGui.QWidget.__init__(self)
            self.label = QtGui.QLabel(self)
            self.edit = QtGui.QLineEdit(self)
            self.edit.returnPressed.connect(self.handleTextEntered)
            layout = QtGui.QVBoxLayout(self)
            layout.addWidget(self.label)
            layout.addWidget(self.edit)
    
        def handleTextEntered(self):
            text = unicode(self.edit.text())
            self.label.setPixmap(
                qrcode.make(text, image_factory=Image).pixmap())
    
    if __name__ == '__main__':
    
        import sys
        app = QtGui.QApplication(sys.argv)
        window = Window()
        window.setGeometry(500, 300, 200, 200)
        window.show()
        sys.exit(app.exec_())
    

    【讨论】:

      【解决方案2】:

      您也可以使用 PNG 作为中间格式,并使用 StringIO 将其存储在内存中。

      import qrcode
      import StringIO
      
      def set_qr_label(label, text):
          """
          set qrcode image on QLabel
      
          @param label: QLabel
          @param text: text for the QR code
          """
          buf = StringIO.StringIO()
          img = qrcode.make(text)
          img.save(buf, "PNG")
          label.setText("")
          qt_pixmap = QtGui.QPixmap()
          qt_pixmap.loadFromData(buf.getvalue(), "PNG")
          label.setPixmap(qt_pixmap)
      

      【讨论】:

        【解决方案3】:

        mgmax 的好答案,但仅限 Python2。对于 Python3 使用:

        import qrcode
        from io import BytesIO
        
        def set_qr_label(label, text):
            """
            set qrcode image on QLabel
        
            @param label: QLabel
            @param text: text for the QR code
            """
            buf = BytesIO()
            img = qrcode.make(text)
            img.save(buf, "PNG")
            label.setText("")
            qt_pixmap = QtGui.QPixmap()
            qt_pixmap.loadFromData(buf.getvalue(), "PNG")
            label.setPixmap(qt_pixmap)
        

        【讨论】:

        • 不要引用用户名,插入该用户对python2的答案的链接..
        【解决方案4】:

        这是在 python3 的 pyqt5 中工作的 ekhumoro 答案 希望它可以帮助某人。

        from PyQt5 import QtWidgets, QtCore, QtGui
        import qrcode
        
        class Image(qrcode.image.base.BaseImage):
            def __init__(self, border, width, box_size):
                self.border = border
                self.width = width
                self.box_size = box_size
                size = (width + border * 2) * box_size
                self._image = QtGui.QImage(
                    size, size, QtGui.QImage.Format_RGB16)
                self._image.fill(QtCore.Qt.white)
        
            def pixmap(self):
                return QtGui.QPixmap.fromImage(self._image)
        
            def drawrect(self, row, col):
                painter = QtGui.QPainter(self._image)
                painter.fillRect(
                    (col + self.border) * self.box_size,
                    (row + self.border) * self.box_size,
                    self.box_size, self.box_size,
                    QtCore.Qt.black)
        
            def save(self, stream, kind=None):
                pass
        
        class Window(QtWidgets.QWidget):
            def __init__(self):
                QtWidgets.QWidget.__init__(self)
                self.label = QtWidgets.QLabel(self)
                self.edit = QtWidgets.QLineEdit(self)
                self.edit.returnPressed.connect(self.handleTextEntered)
                layout = QtWidgets.QVBoxLayout(self)
                layout.addWidget(self.label)
                layout.addWidget(self.edit)
        
            def handleTextEntered(self):
                text = self.edit.text()#text = unicode(self.edit.text())
                self.label.setPixmap(
                    qrcode.make(text, image_factory=Image).pixmap())
        
        if __name__ == '__main__':
        
            import sys
            app = QtWidgets.QApplication(sys.argv)
            window = Window()
            window.setGeometry(500, 300, 200, 200)
            window.show()
            sys.exit(app.exec_())
        
        

        【讨论】:

        • 虽然此代码可能会解决问题,including an explanation 关于如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的回答添加解释并说明适用的限制和假设。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-24
        • 2014-11-13
        • 2012-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多