Python-基于PyQt5,qrcode,PIL,sys的二维码生成工具

前言:二维码(2-dimensional bar code)又称二维条码,是移动设备上很流行的一种编码方式,它比传统的条形码(Bar Code)能存更多信息,能表示更多的数据类型。其根据某种特定的几何图形和规律,在二维平面上利用黑白相间的图形来记录数据信息。二维码在代码编制上巧妙地利用构成计算机内部逻辑基础的“0”“1”比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图像输入设备或光电扫描设备自动识读以实现信息自动处理。在我们的生活中,我们常常就会接触到二维码:通过扫描QQ名片添加QQ好友,扫描微信名片添加微信好友,扫描微信支付码支付等。可以这么说,二维码已经完全融入进我们的日常生活了,我们的衣食住行离不开各种各样的二维码。那么好,今天我们就一起来学习如何利用Python编写一款二维码生成工具。

 编程思路:本次编程我们将会调用到Python中的众多库:PyQt5,qrcode,PILsysPyQt5中的QtWidgets用于创建 GUI 应用程序的各种组件,如窗口、按钮、文本框、标签等;QtGui提供了用于处理图形和图像的类;QtCore则提供了本次编程中的核心非GUI功能,如信号和槽机制、事件处理等,它们将联合构建一个具有用户交互功能的二维码生成器应用程序。sys是Python的一个内置模块,它提供了对PyCharm相关的操作和变量的访问。它主要用于与PyCharm进行交互,例如获取命令行参数、控制Python的运行环境、访问系统特定的参数和函数等。PIL库被用于处理二维码图像(具体来说,是PIL库中的Image模块用来打开、调整大小图像和并将图像粘贴在GUI的指定位置)。qrcode库的作用就比较简单,本次qrcode库被用于生成二维码图像(具体来说,我们将会调用qrcode中的QRCode类来创建一个二维码对象,然后通过调用add_data方法添加要编码的数据,最后调用make方法生成二维码图像。当然,这里会调用到PyQt5中QtWidgets类中的方法获得文本框中的文本内容)。

第一步:导入库

标准库:sys,PIL。

第三方库:PyQt5,qrcode。

#导入库
import sys
import qrcode
from PIL import Image
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

第二步:创建功能类

接下来我们将会创建一个功能类:QRGenerator类。

在这个类中我们将把整个类分为窗口生成区和功能函数区:窗口生成区负责整个窗口的生成以及窗口中按钮,文本框,标签,菜单栏等控件的排版布局。功能函数区负责将用户事件与GUI控件联系起来,实现包括设置前景色,后景色...以及生成,保存二维码等功能的内部逻辑实现。

#功能主类
class QRGenerator(QMainWindow):
    #初始化函数
    def __init__(self):
        super().__init__()
        self.initUI()
        self.setWindowTitle("高级二维码生成器")
        self.setMinimumSize(800, 600)

    #窗口生成区SSS
    #窗口初始化函数
    def initUI(self):
        #创建中心部件和布局
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QHBoxLayout(central_widget)

        #窗口左侧设置区
        control_panel = QGroupBox("设置")
        control_layout = QFormLayout()

        #文本输入框
        self.text_input = QTextEdit()
        self.text_input.setPlaceholderText("输入文本或URL...")

        #颜色拾取器
        self.fg_color = QPushButton("选择前景色")
        self.fg_color.clicked.connect(self.choose_color)
        self.bg_color = QPushButton("选择背景色")
        self.bg_color.clicked.connect(self.choose_color)
        self.colors = {'fg': (0, 0, 0), 'bg': (255, 255, 255)}

        #差错级别
        self.error_correction = QComboBox()
        self.error_correction.addItems([
            '低 (Lower)',
            '中 (Medium)',
            '高 (High)',
            '最高 (Peak)'])

        #设置二维码尺寸
        self.size_spin = QSpinBox()
        self.size_spin.setRange(1, 40)
        self.size_spin.setValue(10)

        #自定义Logo
        self.logo_btn = QPushButton("添加Logo")
        self.logo_btn.clicked.connect(self.add_logo)
        self.logo_path = None

        #生成按钮
        generate_btn = QPushButton("生成二维码")
        generate_btn.clicked.connect(self.generate_qr)

        #保存按钮
        save_btn = QPushButton("保存二维码")
        save_btn.clicked.connect(self.save_qr)

        #添加到布局
        control_layout.addRow("内容:", self.text_input)
        control_layout.addRow("前景色:", self.fg_color)
        control_layout.addRow("背景色:", self.bg_color)
        control_layout.addRow("容错级别:", self.error_correction)
        control_layout.addRow("尺寸:", self.size_spin)
        control_layout.addRow("Logo:", self.logo_btn)
        control_layout.addRow(generate_btn)
        control_layout.addRow(save_btn)
        control_panel.setLayout(control_layout)

        #右侧区域
        self.preview_label = QLabel()
        self.preview_label.setAlignment(Qt.AlignCenter)
        self.preview_label.setStyleSheet("border: 1px solid #ccc;")

        # 主布局
        layout.addWidget(control_panel, 1)
        layout.addWidget(self.preview_label, 2)

    #功能函数区SSS
    def choose_color(self):
        btn = self.sender()
        color = QColorDialog.getColor()
        if color.isValid():
            rgb = color.getRgb()[:3]
            if btn == self.fg_color:
                self.colors['fg'] = rgb
            else:
                self.colors['bg'] = rgb
    #SSS
    def add_logo(self):
        path, _ = QFileDialog.getOpenFileName(
            self, "选择Logo", "", "图片文件 (*.png *.jpg *.bmp)")
        if path:
            self.logo_path = path

    def generate_qr(self):
        text = self.text_input.toPlainText()
        if not text:
            QMessageBox.warning(self, "警告", "请输入内容!")
            return

        try:
            qr = qrcode.QRCode(
                version=self.size_spin.value(),
                error_correction=self.get_error_correction(),
                box_size=10,
                border=4
            )
            qr.add_data(text)
            qr.make(fit=True)
            img = qr.make_image(
                fill_color=self.colors['fg'],
                back_color=self.colors['bg']
            ).convert('RGB')
            if self.logo_path:
                logo = Image.open(self.logo_path)
                img = self.add_logo_to_qr(img, logo)

            #二维码预览
            self.qr_img = img
            self.update_preview()

        except Exception as e:#异常处理显示
            QMessageBox.critical(self, "错误", str(e))

    def add_logo_to_qr(self, qr_img, logo):
        # 计算Logo大小(最大为二维码的1/4,阈值)
        max_size = (qr_img.size[0] // 4, qr_img.size[1] // 4)
        logo.thumbnail(max_size, Image.Resampling.LANCZOS)

        pos = (
            (qr_img.size[0] - logo.size[0]) // 2,
            (qr_img.size[1] - logo.size[1]) // 2
        )
        qr_img.paste(logo, pos)
        return qr_img

    def update_preview(self):
        img = self.qr_img.resize((400, 400), Image.Resampling.LANCZOS)
        img = img.convert("RGBA")
        data = img.tobytes("raw", "RGBA")
        qimg = QImage(data, img.size[0], img.size[1], QImage.Format_RGBA8888)
        self.preview_label.setPixmap(QPixmap.fromImage(qimg))

    def save_qr(self):
        if not hasattr(self, 'qr_img'):
            return
        path, _ = QFileDialog.getSaveFileName(
            self, "保存二维码", "",
            "PNG图片 (*.png);;JPEG图片 (*.jpg);;BMP图片 (*.bmp)")
        if path:
            self.qr_img.save(path)

    def get_error_correction(self):
        correction = {
            0: qrcode.constants.ERROR_CORRECT_L,
            1: qrcode.constants.ERROR_CORRECT_M,
            2: qrcode.constants.ERROR_CORRECT_Q,
            3: qrcode.constants.ERROR_CORRECT_H
        }
        return correction.get(self.error_correction.currentIndex())
    #SSS

第三步:创建驱动程序单元

接下来我们需要创建一段代码,这段代码将负责驱动整个功能类中函数的执行。

#驱动程序单元
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = QRGenerator()
    window.show()
    sys.exit(app.exec_())

第四步:完整代码展示

#导入库
import sys
import qrcode
from PIL import Image
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

#功能主类
class QRGenerator(QMainWindow):
    #初始化函数
    def __init__(self):
        super().__init__()
        self.initUI()
        self.setWindowTitle("高级二维码生成器")
        self.setMinimumSize(800, 600)

    #窗口生成区SSS
    #窗口初始化函数
    def initUI(self):
        #创建中心部件和布局
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QHBoxLayout(central_widget)

        #窗口左侧设置区
        control_panel = QGroupBox("设置")
        control_layout = QFormLayout()

        #文本输入框
        self.text_input = QTextEdit()
        self.text_input.setPlaceholderText("输入文本或URL...")

        #颜色拾取器
        self.fg_color = QPushButton("选择前景色")
        self.fg_color.clicked.connect(self.choose_color)
        self.bg_color = QPushButton("选择背景色")
        self.bg_color.clicked.connect(self.choose_color)
        self.colors = {'fg': (0, 0, 0), 'bg': (255, 255, 255)}

        #差错级别
        self.error_correction = QComboBox()
        self.error_correction.addItems([
            '低 (Lower)',
            '中 (Medium)',
            '高 (High)',
            '最高 (Peak)'])

        #设置二维码尺寸
        self.size_spin = QSpinBox()
        self.size_spin.setRange(1, 40)
        self.size_spin.setValue(10)

        #自定义Logo
        self.logo_btn = QPushButton("添加Logo")
        self.logo_btn.clicked.connect(self.add_logo)
        self.logo_path = None

        #生成按钮
        generate_btn = QPushButton("生成二维码")
        generate_btn.clicked.connect(self.generate_qr)

        #保存按钮
        save_btn = QPushButton("保存二维码")
        save_btn.clicked.connect(self.save_qr)

        #添加到布局
        control_layout.addRow("内容:", self.text_input)
        control_layout.addRow("前景色:", self.fg_color)
        control_layout.addRow("背景色:", self.bg_color)
        control_layout.addRow("容错级别:", self.error_correction)
        control_layout.addRow("尺寸:", self.size_spin)
        control_layout.addRow("Logo:", self.logo_btn)
        control_layout.addRow(generate_btn)
        control_layout.addRow(save_btn)
        control_panel.setLayout(control_layout)

        #右侧区域
        self.preview_label = QLabel()
        self.preview_label.setAlignment(Qt.AlignCenter)
        self.preview_label.setStyleSheet("border: 1px solid #ccc;")

        # 主布局
        layout.addWidget(control_panel, 1)
        layout.addWidget(self.preview_label, 2)

    #功能函数区SSS
    def choose_color(self):
        btn = self.sender()
        color = QColorDialog.getColor()
        if color.isValid():
            rgb = color.getRgb()[:3]
            if btn == self.fg_color:
                self.colors['fg'] = rgb
            else:
                self.colors['bg'] = rgb
    #SSS
    def add_logo(self):
        path, _ = QFileDialog.getOpenFileName(
            self, "选择Logo", "", "图片文件 (*.png *.jpg *.bmp)")
        if path:
            self.logo_path = path

    def generate_qr(self):
        text = self.text_input.toPlainText()
        if not text:
            QMessageBox.warning(self, "警告", "请输入内容!")
            return

        try:
            qr = qrcode.QRCode(
                version=self.size_spin.value(),
                error_correction=self.get_error_correction(),
                box_size=10,
                border=4
            )
            qr.add_data(text)
            qr.make(fit=True)
            img = qr.make_image(
                fill_color=self.colors['fg'],
                back_color=self.colors['bg']
            ).convert('RGB')
            if self.logo_path:
                logo = Image.open(self.logo_path)
                img = self.add_logo_to_qr(img, logo)

            #二维码预览
            self.qr_img = img
            self.update_preview()

        except Exception as e:#异常处理显示
            QMessageBox.critical(self, "错误", str(e))

    def add_logo_to_qr(self, qr_img, logo):
        # 计算Logo大小(最大为二维码的1/4,阈值)
        max_size = (qr_img.size[0] // 4, qr_img.size[1] // 4)
        logo.thumbnail(max_size, Image.Resampling.LANCZOS)

        pos = (
            (qr_img.size[0] - logo.size[0]) // 2,
            (qr_img.size[1] - logo.size[1]) // 2
        )
        qr_img.paste(logo, pos)
        return qr_img

    def update_preview(self):
        img = self.qr_img.resize((400, 400), Image.Resampling.LANCZOS)
        img = img.convert("RGBA")
        data = img.tobytes("raw", "RGBA")
        qimg = QImage(data, img.size[0], img.size[1], QImage.Format_RGBA8888)
        self.preview_label.setPixmap(QPixmap.fromImage(qimg))

    def save_qr(self):
        if not hasattr(self, 'qr_img'):
            return
        path, _ = QFileDialog.getSaveFileName(
            self, "保存二维码", "",
            "PNG图片 (*.png);;JPEG图片 (*.jpg);;BMP图片 (*.bmp)")
        if path:
            self.qr_img.save(path)

    def get_error_correction(self):
        correction = {
            0: qrcode.constants.ERROR_CORRECT_L,
            1: qrcode.constants.ERROR_CORRECT_M,
            2: qrcode.constants.ERROR_CORRECT_Q,
            3: qrcode.constants.ERROR_CORRECT_H
        }
        return correction.get(self.error_correction.currentIndex())
    #SSS

#驱动程序单元
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = QRGenerator()
    window.show()
    sys.exit(app.exec_())

第五步:运行效果展示

由于原版二维码发不出来,我在二维码中加了一个不透明背景的Logo图片。

第六步:操作方法

使用方法:
1. 输入需要生成二维码的文本或URL(统一资源定位符)。
2. 自行设置颜色、容错级别和尺寸。
3. (可选)添加Logo图片(透明Logo图片不影响)
4. 点击生成二维码进行预览。
5. 满意后选择存放路径,然后点击保存到本地。

第七步:注意事项

1,添加Logo时建议使用透明背景的PNG图片。
2,较大的version值会生成更复杂的二维码(适用于更多数据)。
3,更高的容错级别可以增加二维码的破损容错能力。
4,保存时选择不同扩展名即可保存为不同格式。                                                                                5,欠缺Logo图片预览和前,背景色预览等功能。

后面我还会继续优化,敬请期待!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闪云-微星

感谢大家的支持与鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值