系列启语
作者属计算机在读本科生,编写的大部分内容属于个人原创,发文章的目的一是为了总结自己的学习路程,帮助正在学习这方面的人士,二是为了能吸引更优秀的人对文章提出建议,共同进步。
更新速度根据个人时间安排,预计会在十一之前完成。
篇幅原因,此文章只包含两个内容。
信号槽
信号与槽函数
信号槽可以说是 PyQt甚至Qt 最重要的机制之一。
信号,顾名思义是一种发散的类似广播的“标志位”。当用户点击某个按钮,框选某个选项...都会有独自的”广播“信号,如果有对象对这个信号感兴趣,可以使用连接(connect)函数,将某个响应函数与此信号连接。
将某个信号和自己的一个需求函数(称为槽函数)绑定来响应这个信号。当信号产生时,被连接的槽函数会自动执行调用。
一个信号可以连接到多个槽函数上,也可以将多个信号连接到同一个槽函数。
槽函数分两种,一种是不同控件内置的槽函数,还有一种是我们自己定义的槽函数。
简单实例
制作简单计算器窗口
1. 打开qtDesigner
通过PyCharm外部工具方式打开QtDesigner:
具体添加方法在设置中可以添加外部工具(External Tools)
方法类似与Keil5中添加VsCode或TiSyscfg
找出QtDesigner可执行程序,复制快捷方式至桌面:
designer.exe文件地址(默认:虚拟环境):
工程文件/venv/Lib/site-packages/qt6_applications/Qt/bin/designer.exe
2. 设计UI页面
必须要清楚的一点是,即使一个简单的计算器窗口也不能仅仅依靠QtDesigner实现,QtDesigner是可视化设计UI页面的工具,它并不能详细的编写代码,具体的一些逻辑还是需要在代码层面实现。
创建QWidget,自定义窗口大小等。
添加控件,QLineEdit,QLabel,QPushButton。
3. PyUIC 转ui文件为python文件
保存此ui文件,PyCharm中使用 PyUIC 转ui文件为python文件:
选中ui文件,按照上述方法打开外部工具PyUIC,得到同名的python代码文件。
pyuic生成的代码文件是QtDesigner下经过特殊的方法转化出来的代码,此时在pycharm下运行是不会有结果的。
我们在做自己的应用程序或者只是一个窗口时,都是讲ui文件的代码复制到一个新的python文件中,添加固定代码框架(下一步骤会提到)即可运行。
4. 得到可运行的代码
代码框架得到可运行的pyqt代码:具体要添加 / 修改的地方见代码注释。
CSDN_Demo.ui经过PyUIC生成的代码为:
# Form implementation generated from reading ui file 'CSDN_Demo.ui'
#
# Created by: PyQt6 UI code generator 6.7.1
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(400, 200)
self.lineEdit = QtWidgets.QLineEdit(parent=Form)
self.lineEdit.setGeometry(QtCore.QRect(20, 60, 61, 51))
self.lineEdit.setObjectName("lineEdit")
self.lineEdit_2 = QtWidgets.QLineEdit(parent=Form)
self.lineEdit_2.setGeometry(QtCore.QRect(160, 60, 61, 51))
self.lineEdit_2.setObjectName("lineEdit_2")
self.label = QtWidgets.QLabel(parent=Form)
self.label.setGeometry(QtCore.QRect(100, 60, 41, 41))
font = QtGui.QFont()
font.setPointSize(36)
self.label.setFont(font)
self.label.setObjectName("label")
self.lineEdit_3 = QtWidgets.QLineEdit(parent=Form)
self.lineEdit_3.setGeometry(QtCore.QRect(320, 60, 61, 51))
self.lineEdit_3.setObjectName("lineEdit_3")
self.pushButton = QtWidgets.QPushButton(parent=Form)
self.pushButton.setGeometry(QtCore.QRect(230, 70, 75, 24))
self.pushButton.setObjectName("pushButton")
self.label_2 = QtWidgets.QLabel(parent=Form)
self.label_2.setGeometry(QtCore.QRect(130, 140, 151, 31))
font = QtGui.QFont()
font.setPointSize(16)
self.label_2.setFont(font)
self.label_2.setObjectName("label_2")
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.label.setText(_translate("Form", "+"))
self.pushButton.setText(_translate("Form", "等于"))
self.label_2.setText(_translate("Form", "加法计算器窗口"))
复制拷贝到file.py中,可执行代码:
import sys
from PyQt6 import QtCore, QtGui, QtWidgets
from PyQt6.QtWidgets import QWidget, QApplication
# 此class 类名字可以改变,但是需要继承QWidget,因为我们创建的窗口是QWidget
# 如果是QMainWindow就对应继承QMainWindow,
class Ui_Form(QWidget):
def __init__(self):
super(QWidget, self).__init__() # 需要执行QWidget的初始化,这里的变量与上述变量同
self.setupUi(self)
# -------------以下内容不改变------------- #
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(400, 200)
self.lineEdit = QtWidgets.QLineEdit(parent=Form)
self.lineEdit.setGeometry(QtCore.QRect(20, 60, 61, 51))
self.lineEdit.setObjectName("lineEdit")
self.lineEdit_2 = QtWidgets.QLineEdit(parent=Form)
self.lineEdit_2.setGeometry(QtCore.QRect(160, 60, 61, 51))
self.lineEdit_2.setObjectName("lineEdit_2")
self.label = QtWidgets.QLabel(parent=Form)
self.label.setGeometry(QtCore.QRect(100, 60, 41, 41))
font = QtGui.QFont()
font.setPointSize(36)
self.label.setFont(font)
self.label.setObjectName("label")
self.lineEdit_3 = QtWidgets.QLineEdit(parent=Form)
self.lineEdit_3.setGeometry(QtCore.QRect(320, 60, 61, 51))
self.lineEdit_3.setObjectName("lineEdit_3")
self.pushButton = QtWidgets.QPushButton(parent=Form)
self.pushButton.setGeometry(QtCore.QRect(230, 70, 75, 24))
self.pushButton.setObjectName("pushButton")
self.label_2 = QtWidgets.QLabel(parent=Form)
self.label_2.setGeometry(QtCore.QRect(130, 140, 151, 31))
font = QtGui.QFont()
font.setPointSize(16)
self.label_2.setFont(font)
self.label_2.setObjectName("label_2")
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.label.setText(_translate("Form", "+"))
self.pushButton.setText(_translate("Form", "等于"))
self.label_2.setText(_translate("Form", "加法计算器窗口"))
# -------------以上内容不改变------------- #
# 主函数程序,固定。
if __name__ == "__main__":
app = QApplication(sys.argv)
ui = Ui_Form() # 将此ui类给某个变量,这里将此ui类赋值给变量ui
ui.show() # 展示
sys.exit(app.exec()) # 保持窗口不消失,PyQt5会多一个下划线
5. 编写槽函数逻辑代码
面向对象编程,在此ui类下编写加法运算函数,在PushButton相关代码下连接按下信号至此运算函数。
self.pushButton = QtWidgets.QPushButton(parent=Form)
self.pushButton.setGeometry(QtCore.QRect(230, 70, 75, 24))
self.pushButton.setObjectName("pushButton")
# 将PushButton按下的信号连接至响应函数
self.pushButton.clicked.connect(self.Calculate)
def Calculate(self):
a = int(self.lineEdit.text())
b = int(self.lineEdit_2.text())
c = a + b # 简单整形加法运算
self.lineEdit_3.setText(str(a + b))
6. 预览结果
7. 全部代码
import sys
from PyQt6 import QtCore, QtGui, QtWidgets
from PyQt6.QtWidgets import QWidget, QApplication
class Ui_Form(QWidget):
def __init__(self):
super(QWidget, self).__init__()
self.setupUi(self)
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(400, 200)
self.lineEdit = QtWidgets.QLineEdit(parent=Form)
self.lineEdit.setGeometry(QtCore.QRect(20, 60, 61, 51))
self.lineEdit.setObjectName("lineEdit")
self.lineEdit_2 = QtWidgets.QLineEdit(parent=Form)
self.lineEdit_2.setGeometry(QtCore.QRect(160, 60, 61, 51))
self.lineEdit_2.setObjectName("lineEdit_2")
self.label = QtWidgets.QLabel(parent=Form)
self.label.setGeometry(QtCore.QRect(100, 60, 41, 41))
font = QtGui.QFont()
font.setPointSize(36)
self.label.setFont(font)
self.label.setObjectName("label")
self.lineEdit_3 = QtWidgets.QLineEdit(parent=Form)
self.lineEdit_3.setGeometry(QtCore.QRect(320, 60, 61, 51))
self.lineEdit_3.setObjectName("lineEdit_3")
self.pushButton = QtWidgets.QPushButton(parent=Form)
self.pushButton.setGeometry(QtCore.QRect(230, 70, 75, 24))
self.pushButton.setObjectName("pushButton")
# 将PushButton按下的信号连接至响应函数
self.pushButton.clicked.connect(self.Calculate)
self.label_2 = QtWidgets.QLabel(parent=Form)
self.label_2.setGeometry(QtCore.QRect(130, 140, 151, 31))
font = QtGui.QFont()
font.setPointSize(16)
self.label_2.setFont(font)
self.label_2.setObjectName("label_2")
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.label.setText(_translate("Form", "+"))
self.pushButton.setText(_translate("Form", "等于"))
self.label_2.setText(_translate("Form", "加法计算器窗口"))
def Calculate(self):
a = int(self.lineEdit.text())
b = int(self.lineEdit_2.text())
c = a + b # 简单整形加法运算
self.lineEdit_3.setText(str(a + b))
if __name__ == "__main__":
app = QApplication(sys.argv)
ui = Ui_Form()
ui.show()
sys.exit(app.exec())
多窗口调用
在自主设计所需要的应用程序时,经常遇到这样的情形:用户端需要通过点击某个按钮进入到下一个页面、打开新的窗口。比如,设计简单图书管理系统,需要有登录页面,主页面,添加书籍的页面等等。
如何在A.py中连接某个信号至另一个B.py函数的ui类以达到多窗口的调用呢?
简单实例
综上,制作一个欢迎页面,点击进入按钮后进入简易加法计算器页面,点击退出按钮即退出窗口。
按照上述方法得到:
import sys
from PyQt6 import QtCore, QtGui, QtWidgets
from PyQt6.QtWidgets import QWidget, QApplication
# 更改此ui类名,避免重复
class Welcome_Form(QWidget):
def __init__(self):
super(QWidget, self).__init__()
self.setupUi(self)
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(400, 200)
self.Label = QtWidgets.QLabel(parent=Form)
self.Label.setGeometry(QtCore.QRect(90, 30, 201, 71))
font = QtGui.QFont()
font.setPointSize(36)
self.Label.setFont(font)
self.Label.setObjectName("Label")
self.PushButton_Queren = QtWidgets.QPushButton(parent=Form)
self.PushButton_Queren.setGeometry(QtCore.QRect(240, 120, 111, 61))
font = QtGui.QFont()
font.setPointSize(16)
self.PushButton_Queren.setFont(font)
self.PushButton_Queren.setObjectName("PushButton_Queren")
self.PushButton_Quxiao = QtWidgets.QPushButton(parent=Form)
self.PushButton_Quxiao.setGeometry(QtCore.QRect(40, 120, 111, 61))
font = QtGui.QFont()
font.setPointSize(16)
self.PushButton_Quxiao.setFont(font)
self.PushButton_Quxiao.setObjectName("PushButton_Quxiao")
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.Label.setText(_translate("Form", "欢迎页面"))
self.PushButton_Queren.setText(_translate("Form", "确定"))
self.PushButton_Quxiao.setText(_translate("Form", "取消"))
if __name__ == "__main__":
app = QApplication(sys.argv)
ui = Ui_Form()
ui.show()
sys.exit(app.exec())
多窗口调用代码
import sys
from PyQt6 import QtCore, QtGui, QtWidgets
from PyQt6.QtWidgets import QWidget, QApplication
from PyQt6_Learn.CSDN_Demo_Exe import Ui_Form
class Welcome_Form(QWidget):
def __init__(self):
super(QWidget, self).__init__()
self.setupUi(self)
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(400, 200)
self.Label = QtWidgets.QLabel(parent=Form)
self.Label.setGeometry(QtCore.QRect(90, 30, 201, 71))
font = QtGui.QFont()
font.setPointSize(36)
self.Label.setFont(font)
self.Label.setObjectName("Label")
self.PushButton_Queren = QtWidgets.QPushButton(parent=Form)
self.PushButton_Queren.setGeometry(QtCore.QRect(240, 120, 111, 61))
font = QtGui.QFont()
font.setPointSize(16)
self.PushButton_Queren.setFont(font)
self.PushButton_Queren.setObjectName("PushButton_Queren")
# 确认按钮的点击信号
self.PushButton_Queren.clicked.connect(self.pbt_Queren)
self.PushButton_Quxiao = QtWidgets.QPushButton(parent=Form)
self.PushButton_Quxiao.setGeometry(QtCore.QRect(40, 120, 111, 61))
font = QtGui.QFont()
font.setPointSize(16)
self.PushButton_Quxiao.setFont(font)
self.PushButton_Quxiao.setObjectName("PushButton_Quxiao")
# 取消按钮的点击信号
self.PushButton_Quxiao.clicked.connect(self.pbt_Quxiao)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.Label.setText(_translate("Form", "欢迎页面"))
self.PushButton_Queren.setText(_translate("Form", "确定"))
self.PushButton_Quxiao.setText(_translate("Form", "取消"))
def pbt_Queren(self):
welcome.close()
ui.show()
def pbt_Quxiao(self):
welcome.close()
if __name__ == "__main__":
app = QApplication(sys.argv)
welcome = Welcome_Form()
ui = Ui_Form()
welcome.show()
sys.exit(app.exec())
结语与预告
如果本文对你有帮助,还请点赞评论哦!
系列后期内容:
HTML网页调用
Pyserial串口通信
OpenCV与PyQt