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