Python Qt GUI设计入门自建信号与槽函数关联
Posted 肆拾伍
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python Qt GUI设计入门自建信号与槽函数关联相关的知识,希望对你有一定的参考价值。
前言
信号与槽函数有以下几个特点:
- 一个信号可以关联多个槽函数。
- 一个信号可以关联其他信号。
- 信号的参数可以是任何Python数据类型。
- 一个槽函数可以和多个信号关联。
- 关联可以是同步也可以是异步的。
- 可以在不同线程之间建立关联。
上一章讲了一般内置信号和内置槽函数的关联使用,本章将介绍一些特殊情况以及,自定义信号和槽函数的使用。
一、重载overload信号的关联
名称相同但是参数个数或者类型不同的信号称为重载overload信号,这里我们可以看到之前选择信号时的图片:
这两个clicked信号的触发条件都一样,但是一个有返回参数,即如果使用clicked(bool),关联的槽函数会得到一个bool类型的输入参数。那么,这两个信号应该怎么使用呢?我们以上一章的代码为例:
如果我们采用的是不带参数的clicked方法,那么通过下面这条语句可以实现自动关联符合命名规则的槽函数。
QtCore.QMetaObject.connectSlotsByName(Dialog)
def on_pushButton_3_clicked(self):
self.ui.plainTextEdit.clear()
如果我们采用的是clicked(bool)信号,即便我们的槽函数命名符合规则,也不会自动关联,反而可能抛出异常退出程序。因为当出现具有相同名称的信号时,默认关联的是不带参数的信号,而槽函数定义的时候指定了输入参数,会导致输入参数不够而出错。
QtCore.QMetaObject.connectSlotsByName(Dialog)
def on_pushButton_3_clicked(self,checked):
print(checked)
self.ui.plainTextEdit.clear()
上述代码应该修改为:
@pyqtSlot(bool) # 修饰器 告诉python 信号有boo类型输入参数l
def on_checkBox_clicked(self,checked):
print(checked)
不过要记得引入相关的库:
from PyQt5.QtCore import Qt,pyqtSlot
完整代码:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'dialog.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
# 文件保存为Proj2_dialog.py
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(360, 240)
self.plainTextEdit = QtWidgets.QPlainTextEdit(Dialog)
self.plainTextEdit.setGeometry(QtCore.QRect(9, 59, 281, 138))
font = QtGui.QFont()
font.setPointSize(20)
font.setBold(True)
font.setWeight(75)
self.plainTextEdit.setFont(font)
self.plainTextEdit.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
self.plainTextEdit.setCenterOnScroll(False)
self.plainTextEdit.setObjectName("plainTextEdit")
self.horizontalLayoutWidget = QtWidgets.QWidget(Dialog)
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(100, 30, 240, 21))
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.radioButton_3 = QtWidgets.QRadioButton(self.horizontalLayoutWidget)
self.radioButton_3.setObjectName("radioButton_3")
self.horizontalLayout.addWidget(self.radioButton_3)
self.radioButton_2 = QtWidgets.QRadioButton(self.horizontalLayoutWidget)
self.radioButton_2.setObjectName("radioButton_2")
self.horizontalLayout.addWidget(self.radioButton_2)
self.radioButton = QtWidgets.QRadioButton(self.horizontalLayoutWidget)
self.radioButton.setObjectName("radioButton")
self.horizontalLayout.addWidget(self.radioButton)
self.horizontalLayoutWidget_3 = QtWidgets.QWidget(Dialog)
self.horizontalLayoutWidget_3.setGeometry(QtCore.QRect(9, 203, 311, 30))
self.horizontalLayoutWidget_3.setObjectName("horizontalLayoutWidget_3")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_3)
self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_3.setSpacing(30)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.pushButton_3 = QtWidgets.QPushButton(self.horizontalLayoutWidget_3)
self.pushButton_3.setObjectName("pushButton_3")
self.horizontalLayout_3.addWidget(self.pushButton_3)
self.pushButton_2 = QtWidgets.QPushButton(self.horizontalLayoutWidget_3)
self.pushButton_2.setObjectName("pushButton_2")
self.horizontalLayout_3.addWidget(self.pushButton_2)
self.pushButton = QtWidgets.QPushButton(self.horizontalLayoutWidget_3)
self.pushButton.setObjectName("pushButton")
self.horizontalLayout_3.addWidget(self.pushButton)
self.label = QtWidgets.QLabel(Dialog)
self.label.setGeometry(QtCore.QRect(20, 10, 81, 20))
self.label.setObjectName("label")
self.horizontalLayoutWidget_2 = QtWidgets.QWidget(Dialog)
self.horizontalLayoutWidget_2.setGeometry(QtCore.QRect(100, 10, 240, 21))
self.horizontalLayoutWidget_2.setObjectName("horizontalLayoutWidget_2")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_2)
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.checkBox_3 = QtWidgets.QCheckBox(self.horizontalLayoutWidget_2)
self.checkBox_3.setObjectName("checkBox_3")
self.horizontalLayout_2.addWidget(self.checkBox_3)
self.checkBox_2 = QtWidgets.QCheckBox(self.horizontalLayoutWidget_2)
self.checkBox_2.setObjectName("checkBox_2")
self.horizontalLayout_2.addWidget(self.checkBox_2)
self.checkBox = QtWidgets.QCheckBox(self.horizontalLayoutWidget_2)
self.checkBox.setObjectName("checkBox")
self.horizontalLayout_2.addWidget(self.checkBox)
self.label_2 = QtWidgets.QLabel(Dialog)
self.label_2.setGeometry(QtCore.QRect(20, 30, 81, 16))
self.label_2.setObjectName("label_2")
self.retranslateUi(Dialog)
self.pushButton_2.clicked.connect(Dialog.accept)
self.pushButton.clicked.connect(Dialog.close)
# self.checkBox.clicked[bool].connect(Dialog.checkBox_clicked)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.plainTextEdit.setPlainText(_translate("Dialog", "Hello World!"))
self.radioButton_3.setText(_translate("Dialog", "Black "))
self.radioButton_2.setText(_translate("Dialog", "Red "))
self.radioButton.setText(_translate("Dialog", "Blue"))
self.pushButton_3.setText(_translate("Dialog", "清空"))
self.pushButton_2.setText(_translate("Dialog", "确认"))
self.pushButton.setText(_translate("Dialog", "取消"))
self.label.setText(_translate("Dialog", "字体样式"))
self.checkBox_3.setText(_translate("Dialog", "Underline"))
self.checkBox_2.setText(_translate("Dialog", "Italic"))
self.checkBox.setText(_translate("Dialog", "Bold"))
self.label_2.setText(_translate("Dialog", "字体颜色"))
# 新建另一个py文件,名字随意
import sys
from PyQt5.QtWidgets import QDialog,QApplication
from Proj2_dialog import Ui_Dialog
from PyQt5.QtCore import Qt,pyqtSlot
class QmyDialog(QDialog):
def __init__(self):
super().__init__()
self.ui = Ui_Dialog()
self.ui.setupUi(self)
def on_pushButton_3_clicked(self):
self.ui.plainTextEdit.clear()
def on_checkBox_3_toggled(self,checked):
font = self.ui.plainTextEdit.font()
# print(type(font))
font.setUnderline(checked)
self.ui.plainTextEdit.setFont(font)
def on_checkBox_2_toggled(self,checked):
font = self.ui.plainTextEdit.font()
# print(type(font))
font.setItalic(checked)
self.ui.plainTextEdit.setFont(font)
def on_checkBox_toggled(self,checked):
font = self.ui.plainTextEdit.font()
# print(type(font))
font.setBold(checked)
self.ui.plainTextEdit.setFont(font)
@pyqtSlot(bool)
def on_checkBox_clicked(self,checked):
print(checked)
if __name__ =="__main__":
app = QApplication(sys.argv)
mydialog = QmyDialog()
mydialog.show()
sys.exit(app.exec_())
运行结果:
二、自定义信号
自定义信号分为无输入参数,单个输入参数,多个输入参数以及同名但是输入参数类型可变的重载overload信号。
自建信号必须是QObject的子类的属性,PyQt5.QtCore.pyqtSignal()
能够为类建立信号。
代码如下(示例):
import sys
from PyQt5.QtCore import QObject,pyqtSlot,pyqtSignal
class Human(QObject): # 继承QObject,也可以是QObject的子类,比如说QWidget
onePar_overload = pyqtSignal([int],[str])# 单个输入变量,int类型或者str类型
twoPar_overload = pyqtSignal([int,int],[int,str])# 两个输入变量
def onePar(self,int):
print('onepar')
def onePar_str(self,str1):
print('onepar_str')
def twopar(self,int1,int2):
print(int1,int2)
def twopar_str(self,int1,str2):
print(int1,str2)
a = Human()
a.onePar_overload.connect(a.onePar)
a.onePar_overload.emit(1)# 发出信号,默认参数类型是第一个,也就是[int]
a.onePar_overload[str].connect(a.onePar_str)
a.onePar_overload[str].emit("123")# 发出信号,要指定发送信号类型是[str]
a.twoPar_overload.connect(a.twopar)
a.twoPar_overload.emit(1,2)
a.twoPar_overload[int,str].connect(a.twopar_str)
a.twoPar_overload[int,str].emit(1,'132')
# 需要注意的是,这里都需要手动关联,并且槽函数是不能重名的,即使发送信号是同一个信号
# 还是仔细体会代码吧
效果:
总结
我无数次希望把文章写得面面俱到,每个注意的小点都写清楚,但是我做不到,怪我太懒。文章啰里啰嗦就很烦,真的很佩服那些写教程写得清晰易懂的人,有问题还是留言问吧。
以上是关于Python Qt GUI设计入门自建信号与槽函数关联的主要内容,如果未能解决你的问题,请参考以下文章
Python Qt GUI设计:信号与槽的使用方法(基础篇—7)