前言
大家好,这里是Seon塞翁。本实战项目为构建一个桌面应用,功能是定制二维码,实现多种数据类型的嵌入,和二维码样式的多样化。
涉及知识点:基于 PyQt5 的界面构建和功能实现(包括标签、按钮、文本框、滑块、选项卡、工具箱、菜单栏、状态栏等控件),界面国际化(文字英汉互译),基于qrcode和myqr库定制二维码(颜色、logo、背景图),用 qrc 文件管理打包资源。
阅读前应具备 Python 基础和对 PyQt5 库的入门知识(可见 PyQt5初学试验记录系列文章)。
文章目录
一、打包后的工具使用效果预览
1、生成普通二维码

2、生成带 Logo 的二维码

3、生成有背景图的二维码

p.s.大家可以试着扫一下三个二维码看看结果。
二、MainWindow中的主要控件
首先考虑主窗口的基本设计。因需要用到菜单栏和状态栏,本次采用 MainWindow 来作为主界面。首先在界面中添加两个 GroupBox 控件,用于将控件分类。左边为参数区,右边的正方形用于显示二维码。

修改 GroupBox 名称,继续添加其他控件。在左侧添加 ToolBox 工具箱控件,该控件以抽屉的方式显示多级窗口。笔者设置了 3 个抽屉(第 4 个为笔者测试用)分别用于放置链接、多行文本、电子名片等 3 类数据的输入窗口。在右侧显示二维码区域的下方,放置一个 tabWidget 选项卡控件,其具有颜色和图片两个选项卡,分别用于设置二维码的前景色和背景图片。

三、输入区中的控件细节
接着来看数据输入区,第一个抽屉是输入链接,预设了链接的头部,用户可以在此输入网址,之后扫描生成的二维码即可进入网站。

第二个抽屉是输入无格式的多行文本,建议字数限制为 200。在多行文本框下方添加标签用于显示字数,因 TextEdit 不像 LineEdit 控件那样可以设置清空提示,故需添加一个按钮用于手动清空内容。此外,本界面未采用多线程设计,为避免在每次修改多行文本(如打一个或多个字)就调用生成二维码的方法时可能造成的界面卡顿,初步设计为增加一个按钮用于在用户确定完成输入后,再生成二维码(本部分仍存在问题,将在后续章节说明)。

第三个抽屉是输入电子名片,用多个标签和单行文本框的组合即可。

如下为后续会使用到的控件对象的命名:
| 序号 | 所属位置 | 控件 | Objectname |
|---|---|---|---|
| 1 | URL | 单行文本 | lineEdit_url |
| 2 | TEXT | 多行文本 | textEdit |
| 3 | TEXT | 标签 | label_words_nums |
| 4 | TEXT | 按钮 | pb_clean_text |
| 5 | TEXT | 按钮 | pb_getQR |
| 6 | CARD | 单行文本 | lineEdit_name |
| 7 | CARD | 单行文本 | lineEdit_tel |
| 8 | CARD | 单行文本 | lineEdit_qq |
| 9 | CARD | 单行文本 | lineEdit_mail |
| 10 | CARD | 单行文本 | lineEdit_company |
| 11 | CARD | 单行文本 | lineEdit_website |
四、二维码显示及样式区中的控件细节
在显示二维码的区域中,添加一个 label 标签控件用于加载图像。

第一个选项卡为预设的颜色按钮,及颜色代码输入区。

第二个选项卡为图像设置,通过单选按钮选择 logo 或背景图的模式,通过滑块调整背景图的透明度。

如下为后续会使用到的控件对象的命名:
| 序号 | 所属位置 | 控件 | Objectname |
|---|---|---|---|
| 1 | QR Code | 标签 | label_result |
| 2 | Color选项卡 | 按钮 | pb_0 |
| 3 | Color选项卡 | 按钮 | pb_1 |
| 4 | Color选项卡 | 按钮 | pb_2 |
| 5 | Color选项卡 | 按钮 | pb_3 |
| 6 | Color选项卡 | 按钮 | pb_4 |
| 7 | Color选项卡 | 按钮 | pb_5 |
| 8 | Color选项卡 | 按钮 | pb_6 |
| 9 | Color选项卡 | 按钮 | pb_7 |
| 10 | Color选项卡 | 单行文本 | lineEdit_color_code |
| 11 | Color选项卡 | 按钮 | pb_color_enter |
| 12 | Image选项卡 | 单选按钮 | radioButton_0 |
| 13 | Image选项卡 | 单选按钮 | radioButton_1 |
| 14 | Image选项卡 | 按钮 | pb_openfile |
| 15 | Image选项卡 | 单行文本 | lineEdit_filepath |
| 16 | Image选项卡 | 滑块 | slider_depth |
| 17 | Image选项卡 | 标签 | label_depth |
五、菜单栏和界面调整
继续在菜单栏中添加另存为、关于和语言的子菜单。如上图,红框部分为自行添加的内容。

其对象命名如下:
| 序号 | 所属位置 | 控件 | Objectname |
|---|---|---|---|
| 1 | 一级菜单 | 菜单栏 | actionSave_as |
| 2 | 一级菜单 | 菜单栏 | actionAbout |
| 3 | 二级菜单 | 菜单栏 | actionChinese |
| 4 | 二级菜单 | 菜单栏 | actionEnglish |
再美化一下界面,通过 setItemIcon() 方法为工具箱加上图标。
# 图标 ------------------------------------------------------------
self.toolBox.setItemIcon(0,QIcon(":resource/url.ico"))
self.toolBox.setItemIcon(1, QIcon(":resource/text.ico"))
self.toolBox.setItemIcon(2, QIcon(":resource/card.ico"))

可以看到上面的样例图中,按钮被设置成了不同的颜色,如何用简单的语句来实现呢?答案是利用 for 循环:先准备一个存放默认颜色代码的列表,接着在 for 循环中通过 getattr() 方法获取每一个按钮对象,调用其 setStyleSheet 方法设置颜色。这也是在之前为这一组颜色按钮命名为 pb_0 、pb_1 、pb_2 ……的原因。
# 参数 ------------------------------------------------------------
self.color_list = ['#000000', '#DC143C', '#FFA500', '#FFD700', '#90EE90',
'#40E0D0', '#00BFFF','#BA55D3'] # 颜色列表
# 界面控件设置 ------------------------------------------------------------
for n in range (0,len(self.color_list)): # 设置按钮颜色
getattr(self, 'pb_%s'%n).setStyleSheet("background-color: " + self.color_list[n])
以上代码等同于写 n 个 self.pb.setStyleSheet() 语句:
# self.pb_0.setStyleSheet("background-color: black")
# self.pb_1.setStyleSheet("background-color: #DC143C")
# ......
既然如此,还可以用同样的办法为各个文本框加上内容清空提示。
self.edit_list = ['lineEdit_url', 'lineEdit_name', 'lineEdit_tel', 'lineEdit_qq', 'lineEdit_mail',
'lineEdit_company', 'lineEdit_website', 'lineEdit_color_code', 'lineEdit_filepath',
] # 文本框列表
for n in range (0,len(self.edit_list)): # 设置文本框清空提示,多行文本无该功能
getattr(self, self.edit_list[n]).setClearButtonEnabled(True)
但因多行文本框没有便捷的清空方法,需单独加一个清空按钮。
self.pb_clean_text.clicked.connect(self.clean_words)
通过点击按钮将多行文本框的值设为空字符。
def clean_words(self): # 清空输入
self.textEdit.setText("")

设想中的多行文本框下方有生成按钮、字数显示标签和清空文本按钮。生成按钮暂且不提,先来实现一下输入内容的字数显示功能。显示字数的同时,通过弹窗来提示用户,建议字数在 200 以内(强制限制的方法将在后续章节说明)。
def show_words(self): # 显示字数
nums = len(self.textEdit.toPlainText())
self.label_words_nums.setText(self.tr('Length: ')+ ' '*(3 - len(str(nums))) + f'{nums}/200')
if nums > 200:
QMessageBox.about(self,self.tr('Remind'),self.tr('Limit words to 200 !'))
连接文本改变信号和自定义槽函数,即每当文本内容改变时,调用 show_words() 方法。
self.textEdit.textChanged.connect(self.show_words)
最后把用来显示最终二维码图像的 QLabel 控件设置为白色,便于观察它在界面中的位置大小。该控件的颜色设置有点麻烦,幸运的是只需要设置这一个。
palette = QPalette()
palette.setColor(QPalette.Window, Qt.white)
self.label_result.setAutoFillBackground(True)
self.label_result.setPalette(palette) # 设置结果图区域的label为白色背景
六、本章小结
第一章我们演示了二维码生成器的基本使用,并对其前期的界面设计和部分控件设置作了讲解,涉及菜单栏、状态栏、工具箱、标签、选项卡、按钮、文本框、滑块等控件。下一章将继续讲解控件功能的实现,包括数据输入、选择颜色、打开图像、菜单栏动作、状态栏信息等内容,敬请关注!

本文介绍了一个基于PyQt5的桌面应用,演示如何定制二维码,支持嵌入不同数据类型,如链接、文本和电子名片,以及实现二维码样式多样化,包括Logo、背景图和颜色设置。通过详细讲解主窗口、输入区、显示区和菜单栏的控件设置,为初学者提供实用教程。
:基本界面设计&spm=1001.2101.3001.5002&articleId=108822368&d=1&t=3&u=f17d9d11ca43426991c39003fb7090a8)
4572

被折叠的 条评论
为什么被折叠?



