本文采用
PyQt5+QtDesigner
实现GUI(用户界面)的设计,为了方便推荐直接使用PyCharm
作为IDE(代码编辑器)。
0. 安装
首先推荐下载[1]安装好 PyCharm
,然后按照这篇[2]的指引安装好 PyQt5
和对应的工具。
注意文章中有一小段可能过时:在Windows下,安装完 pyqt5-tools
之后,在Python安装目录的\Lib\site-packages\pyqt5-tools\designer文件夹下面可能找不到designer.exe。
你需要到 Python
的安装目录下的 Scripts
文件夹找 pyqt5designer.exe
。文章中的 pyrcc5.exe
和 pyuic5.exe
也在同文件夹中。
Tips: Windows下Python的默认安装目录是 C:\Users\[你的用户名]\AppData\Local\Programs\Python\[你的Python版本]
1. 使用 Qt Designer 设计界面
你可以在这里[3]学到所有需要的知识。或者你很懒不愿意点这个链接的话,就继续往下看吧。
首先在你的 PyCharm
里新建一个空的项目,然后找到 QtDesigner
并打开。
如果你没有找到它,多半是上一步安装的时候没有安装完成,请在工具栏点第一个 File
,下拉菜单选 Settings
,然后找到 Tools\ExternalTools
并添加:
成功打开 Qt Designer 后首先选择一种窗口类型:
其中三个 Dialog
主要用作弹出的小对话窗口,一般窗口使用 Widget
, MainWindow
有格外的菜单栏、工具栏、状态栏等。如果实在不太清楚就直接全都用Widget吧。
然后从左边拖动想要的控件到界面上,选中一个控件,可以在右边修改需要的名字和属性。
注意右边被我选中的 Object
一栏,在这里可以修改对应控件的名字。
保存之后会得到一个 .ui
结尾的文件。在 PyCharm
右键点击它,在右键菜单中选择 ExternalTools/PyUIC
,如果之前设置正确,现在你可以在同目录下看到一个与 .ui
同名的 .py
文件。
打开这个 .py
文件,里面是一个大概长这样的类的定义:
fromPyQt5importQtCore, QtGui, QtWidgets
classUi_Form(object):
# 这是类名,如果你在Qt Designer修改了窗口的名字(在右上
# 方的Object栏里),它会显示其他名字
def setupUi(self, Form): #这里的变量名和上面一样,也是用的窗口名字
Form.setObjectName("Form")
Form.resize(162, 270)
# 你拖进窗口的控件会显示在这里
self.pushButton = QtWidgets.QPushButton(Form)
self.pushButton.setGeometry(QtCore.QRect(40, 140, 71, 21))
self.pushButton.setObjectName("pushButton")
...... # 这里还会有其他的控件
def retranslateUi(self, Form):
......
这时不要修改整个文件,另外新建一个py文件,定义我们自己的窗口类:
# 有些语句需要按照你的文件名调整
# 假设这个文件是"myform.py",上面自动生成的文件是"form.py",两个文件在同文件夹下
import sys
fromPyQt5.QtWidgetsimportQWidget, QApplication
from form importUi_Form
# 我们自己定义一个类
classMyForm(Ui_Form, QWidget): #实际上是继承了这两个类
def __init__(self):
super(MyForm, self).__init__() #基类的初始化
self.setupUi(self) #这个函数是从Ui_Form类里拿过来的,参数是另几个基类QWidget...我还是不解释了
if __name__ == '__main__': #没学过python的同学姑且理解为主函数就好了
app = QApplication(sys.argv) #这句是必须的
main = MyForm() #生成一个MyForm类的变量
main.show() #你没写这个函数?它是从QWidget继承的
sys.exit(app.exec_()) #我们关掉打开的窗口后程序结束
如果没有看懂上面的代码也没关系,把代码复制下来,然后在 PyCharm
下面点进 Terminal
,输入 python[上面这个文件的文件名]
运行,然后就可以欣赏到你设计的窗口了。
2. 信号/槽
上面生成的界面是没法操作的,得想办法让界面上的控件有用,需要修改上面的代码:
# import 就不写了,都一样的
classMyForm(Ui_Form, QWidget):
def __init__(self):
super(QWidget, self).__init__()
self.setupUi(self)
self.pushButton.clicked.connect(self.calculate_sum)
# 把“pushButton被点击了”连接到"calculate_sum"函数
# 你可以输入 self.pushButton. 后等几秒钟,PyCharm会列出所有可能的函数
# 当然这里的 pushButton 只是我的按钮名字,可以到另外一个自动生成的.py文件或者到Qt Designer中去找你自己设置的按钮、文本框等等的名字是什么
# 这个函数是上面"connect"的参数,意思是按下按钮后就会执行这个函数
def calculate_sum(self):
# 获取lineEdit中的文本,并转换类型为int
add1 = int(self.lineEdit.text())
# 获取lineEdit2中的文本,并转换类型为int
add2 = int(self.lineEdit_2.text())
# 在textBrowser中显示求和结果
self.textBrowser.setText("The sum is %d"% (add1+add2,))
# 只学过C的同学可以把这句括号里看成 printf("The sum is %d", add1+add2),注意这里括号里面并不是“输出”,而是通过这样的格式处理出一个“字符串”然后将这个字符串作为参数传递给setText函数
if __name__ == '__main__': #没学过python的同学姑且理解为主函数就好了
app = QApplication(sys.argv)
main = MyForm()
main.show()
sys.exit(app.exec_())
输入 python[上面这个文件的文件名]
运行,你就可以开始玩这个加法器了。
如果输入的不是整数会如何?会报错退出。在Python中一般我们使用 try-except
机制来处理可能的异常,修改 calculate_sum
函数如下:
def calculate_sum(self):
try: #尝试将两个输入框内容转换为整数
add1 = int(self.lineEdit.text())
add2 = int(self.lineEdit_2.text())
self.textBrowser.setText("The sum is %d"% (add1+add2,))
exceptValueError: #如果出现了“ValueError”,即文本框内容不是整数
self.textBrowser.setText("Invalid input")#就干点其他事情
#注意,如果你不知道会报什么类型的错误,只写"except:"就好。虽然这样不够优雅
3.尝试学习更多的信号/槽
我在设计界面的时候选了一个下拉选择框,但完全不知道怎么用怎么办?
点击它,在 QtDesigner
的右边可以看到文本框属于 QComboBox
类,然后去官方文档搜索引擎中直接搜索(或者加上pyqt再搜),就可以在某篇CSDN中找到这样的说明
我们照着上面做加法器的方式,再设计这个下拉框的行为:
classMyForm(Ui_Form, QWidget):
operator= "+"#成员变量,只学过C的同学可以理解为“MyForm结构体内部的变量”
def __init__(self):
super(QWidget, self).__init__()
self.setupUi(self)
self.pushButton.clicked.connect(self.calculate_answer)
#如果你改了对应函数名,记得把这里连接的函数名也改了
self.comboBox.addItems(["+", "-", "*"])
self.comboBox.currentIndexChanged.connect(self.change_operator)
#这些函数的意思上面的图有。总之都能在网上搜到的。
def change_operator(self):
self.operator= self.comboBox.currentText()
# 把成员变量的值设成下拉选框当前的值
def calculate_answer(self): #修改加法器为计算器
try:
num1 = int(self.lineEdit.text())
num2 = int(self.lineEdit_2.text())
answer = 0
ifself.operator== "+":
answer = num1 + num2
elifself.operator== "-":
answer = num1 - num2
else:
answer = num1 * num2
self.textBrowser.setText("The answer is %d"% (answer,))
exceptValueError:
self.textBrowser.setText("Invalid input")
你可以通过这样的方法学期其他控件的使用,包括表格等等,选中/点击/双击/选中一行这些功能也都可以通过搜索在网上找到。你还可以塞背景图片等等。祝大家debug愉快。
4.一些Tips
你可以把
show()
函数包在类里面,这样就可以控制什么时候显示窗口。也可以在窗口类里定义其他类来通过“按钮”等打开其他窗口,但要注意新打开的窗口最好是像上面示例代码的"operator"一样是成员变量。建议数据库操作部分另外写函数/类来做,不要直接往窗口类里塞SQL语句。UI与数据分离可以减少很多debug时间,这样你就不会删一个按钮导致整个项目处处出锅。
如果你是连接到的数据库,一般来说每次运行窗口都是新的,但数据库是旧的,所以要么每次在开头加一句“删库”,要么先不使用连接数据库。
上面的演示中,代码的执行都是由控件触发的。你可以搜索
QtCore.pyqtSignal
如何使用,它可以让你从任何地方触发信号,比如不同窗口之间。观察自动生成的.py文件的代码,你会发现它们在设置你的窗口里的控件的大小,背景等等。永远不要手动改自动生成的.py文件里的代码,实在要改请在Qt Designer中设计。而且你可以在你自己定义的类中再次调用这些函数,来改变窗口大小/背景等等。
仍然可以用
print()
输出,但它们不显示在界面上,显示在你运行python...
的小黑框里,可以当调试窗口用。
注:由于微信公众号不支持非公众号推文的超链接,将文内三处链接手动列举如下:
[1] https://www.jetbrains.com/pycharm/download/
[2] https://blog.csdn.net/qq_37791134/article/details/88357253
[3] http://code.py40.com/face