前言
大家好,这里是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为白色背景
六、本章小结
第一章我们演示了二维码生成器的基本使用,并对其前期的界面设计和部分控件设置作了讲解,涉及菜单栏、状态栏、工具箱、标签、选项卡、按钮、文本框、滑块等控件。下一章将继续讲解控件功能的实现,包括数据输入、选择颜色、打开图像、菜单栏动作、状态栏信息等内容,敬请关注!