通过前面的系列文章学习,我们已经基本上能上手做一个简单的数据分析可视化系统。本次我们详细介绍PyQt5中信号与槽的使用。信号与槽是pyqt5编程的基础与特色,通过信号与槽的编程机制使得处理各界面控件之间的信息交互变得简单和直观。在GUI中,常见的信号有:
GUI程序设计的主要内容便是对界面上的各种控件的特定信号作出响应,然后去处理这些信号即可。而槽(Slot)即是对所触发信号的响应函数。该槽函数一定与信号关联,当信号触发时,槽函数会被自动执行。信号与槽具有以下几个特点:
-
一个信号可以关联多个槽函数。
-
一个信号也可以关联其他信号。
-
一个槽函数可以和多个信号关联
-
......
信号与槽的连接
(1)@pyqtSlot()装饰器槽函数实现
在这种方式下,对槽函数的命名有着特殊的要求:on_(控件对象名称)_信号名(self,内置参数),例如:on_checkBox_clicked()。一个控件同时要与多个信号与槽函数时,只需要写一次@pyqtSlot()。书写简洁,但是不能自由定义槽函数名称。
@pyqtSlot(bool)
def on_checkBox_2_clicked(self, checked):
font = self.ui.plainTextEdit.font()
font.setItalic(checked)
self.ui.plainTextEdit.setFont(font)
(2)connect()
对于槽函数的名称没有特殊要求,对于信号的连接语句遵从如下规则:(控件名称).(信号名称).connect(槽函数名称)。
当参函数带有参数时,如上参函数名称部分为:lambda 参数名:函数名(参数名);而槽函数不带参数时,参函数名称不带()。方便、自由定义,但如果信号较多,书写混乱。
self.ui.radioButton.clicked.connect(self.setTextColor)
# 自定义槽函数
def setTextColor(self):
plet = self.ui.plainTextEdit.palette()
if (self.ui.radioButton.isChecked()):
plet.setColor(QPalette.Text, Qt.blue)
elif (self.ui.radioButton_2.isChecked()):
plet.setColor(QPalette.Text, Qt.green)
elif (self.ui.radioButton_3.isChecked()):
plet.setColor(QPalette.Text, Qt.red)
elif (self.ui.radioButton_4.isChecked()):
plet.setColor(QPalette.Text, Qt.black)
self.ui.plainTextEdit.setPalette(plet)
附上完整小项目案例代码
第一部分:ui文件代码
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(500, 512)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.frame = QtWidgets.QFrame(self.centralwidget)
self.frame.setMinimumSize(QtCore.QSize(0, 40))
self.frame.setMaximumSize(QtCore.QSize(16777215, 40))
font = QtGui.QFont()
font.setFamily("Agency FB")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
self.frame.setFont(font)
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame)
self.horizontalLayout.setObjectName("horizontalLayout")
self.checkBox = QtWidgets.QCheckBox(self.frame)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("C:/Users/yanjiaxi/Pictures/下划线.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.checkBox.setIcon(icon)
self.checkBox.setObjectName("checkBox")
self.horizontalLayout.addWidget(self.checkBox)
self.checkBox_2 = QtWidgets.QCheckBox(self.frame)
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap("C:/Users/yanjiaxi/Pictures/斜体.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.checkBox_2.setIcon(icon1)
self.checkBox_2.setObjectName("checkBox_2")
self.horizontalLayout.addWidget(self.checkBox_2)
self.checkBox_3 = QtWidgets.QCheckBox(self.frame)
icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap("C:/Users/yanjiaxi/Pictures/粗体.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.checkBox_3.setIcon(icon2)
self.checkBox_3.setObjectName("checkBox_3")
self.horizontalLayout.addWidget(self.checkBox_3)
self.checkBox_4 = QtWidgets.QCheckBox(self.frame)
icon3 = QtGui.QIcon()
icon3.addPixmap(QtGui.QPixmap("C:/Users/yanjiaxi/Pictures/删除线.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.checkBox_4.setIcon(icon3)
self.checkBox_4.setObjectName("checkBox_4")
self.horizontalLayout.addWidget(self.checkBox_4)
self.verticalLayout.addWidget(self.frame)
self.frame_2 = QtWidgets.QFrame(self.centralwidget)
self.frame_2.setMinimumSize(QtCore.QSize(0, 40))
self.frame_2.setMaximumSize(QtCore.QSize(16777215, 40))
font = QtGui.QFont()
font.setFamily("Agency FB")
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.frame_2.setFont(font)
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.frame_2)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.radioButton = QtWidgets.QRadioButton(self.frame_2)
self.radioButton.setObjectName("radioButton")
self.horizontalLayout_2.addWidget(self.radioButton)
self.radioButton_2 = QtWidgets.QRadioButton(self.frame_2)
self.radioButton_2.setObjectName("radioButton_2")
self.horizontalLayout_2.addWidget(self.radioButton_2)
self.radioButton_3 = QtWidgets.QRadioButton(self.frame_2)
self.radioButton_3.setObjectName("radioButton_3")
self.horizontalLayout_2.addWidget(self.radioButton_3)
self.radioButton_4 = QtWidgets.QRadioButton(self.frame_2)
self.radioButton_4.setObjectName("radioButton_4")
self.horizontalLayout_2.addWidget(self.radioButton_4)
self.verticalLayout.addWidget(self.frame_2)
self.plainTextEdit = QtWidgets.QPlainTextEdit(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.plainTextEdit.sizePolicy().hasHeightForWidth())
self.plainTextEdit.setSizePolicy(sizePolicy)
self.plainTextEdit.setMaximumSize(QtCore.QSize(16777215, 200))
font = QtGui.QFont()
font.setFamily("Agency FB")
font.setPointSize(12)
font.setBold(True)
font.setWeight(75)
self.plainTextEdit.setFont(font)
self.plainTextEdit.setObjectName("plainTextEdit")
self.verticalLayout.addWidget(self.plainTextEdit)
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setObjectName("lineEdit")
self.verticalLayout.addWidget(self.lineEdit)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setObjectName("pushButton")
self.verticalLayout.addWidget(self.pushButton)
self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 500, 23))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.checkBox.setText(_translate("MainWindow", "下划线"))
self.checkBox_2.setText(_translate("MainWindow", "斜体"))
self.checkBox_3.setText(_translate("MainWindow", "粗体"))
self.checkBox_4.setText(_translate("MainWindow", "删除线"))
self.radioButton.setText(_translate("MainWindow", "蓝色"))
self.radioButton_2.setText(_translate("MainWindow", "绿色"))
self.radioButton_3.setText(_translate("MainWindow", "红色"))
self.radioButton_4.setText(_translate("MainWindow", "橙色"))
self.plainTextEdit.setPlainText(_translate("MainWindow", " 朝中措·平山堂\n"
" 【作者】欧阳修 【朝代】宋\n"
"\n"
" 平山栏槛倚晴空,山色有无中。\n"
" 手种堂前垂柳,别来几度春风?\n"
" 文章太守,挥毫万字,一饮千钟。\n"
" 行乐直须年少,尊前看取衰翁。"))
self.pushButton.setText(_translate("MainWindow", "关闭"))
第二部分:主逻辑代码
##与UI窗体类对应的业务逻辑类
import sys
from PyQt5.QtWidgets import QApplication, QDialog, QMainWindow
from PyQt5.QtGui import QPalette
from PyQt5.QtCore import Qt, pyqtSlot, pyqtSignal
from GUI_EST.slot_test1 import Ui_MainWindow
class mainWindow(QMainWindow):
# 自定义信号,不带参数
button_clicked_signal = pyqtSignal()
def __init__(self):
super(mainWindow,self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
#自定义槽函数connect
self.ui.plainTextEdit.selectionChanged.connect(self.selected_text)
self.ui.radioButton.clicked.connect(self.setTextColor)
self.ui.radioButton_2.clicked.connect(self.setTextColor)
self.ui.radioButton_3.clicked.connect(self.setTextColor)
self.ui.radioButton_4.clicked.connect(self.setTextColor)
# 连接信号与槽函数
self.ui.pushButton.clicked.connect(self.btn_clicked)
# 接收信号,连接到槽函数
self.button_clicked_signal.connect(self.close)
def on_checkBox_3_toggled(self, checked):
font = self.ui.plainTextEdit.font()
font.setBold(checked)
self.ui.plainTextEdit.setFont(font)
def on_checkBox_4_toggled(self, checked):
font = self.ui.plainTextEdit.font()
font.setStrikeOut(checked) #删除线
self.ui.plainTextEdit.setFont(font)
def on_checkBox_clicked(self):
checked = self.ui.checkBox.isChecked()
font = self.ui.plainTextEdit.font()
font.setUnderline(checked)
self.ui.plainTextEdit.setFont(font)
@pyqtSlot(bool)
def on_checkBox_2_clicked(self, checked):
font = self.ui.plainTextEdit.font()
font.setItalic(checked)
self.ui.plainTextEdit.setFont(font)
# 自定义槽函数
def setTextColor(self):
plet = self.ui.plainTextEdit.palette()
if (self.ui.radioButton.isChecked()):
plet.setColor(QPalette.Text, Qt.blue)
elif (self.ui.radioButton_2.isChecked()):
plet.setColor(QPalette.Text, Qt.green)
elif (self.ui.radioButton_3.isChecked()):
plet.setColor(QPalette.Text, Qt.red)
elif (self.ui.radioButton_4.isChecked()):
plet.setColor(QPalette.Text, Qt.black)
self.ui.plainTextEdit.setPalette(plet)
def selected_text(self):
selected_text = self.ui.plainTextEdit.toPlainText()\
[self.ui.plainTextEdit.textCursor().selectionStart():self.ui.plainTextEdit.textCursor().selectionEnd()]
self.ui.lineEdit.setText(selected_text)
def btn_clicked(self):
# 发送自定义信号,无参数
self.button_clicked_signal.emit()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = mainWindow()
window.show()
sys.exit(app.exec_())
本小节,重点介绍pyqt5信号与槽的连接使用,通过简单的案例掌握信号与槽的基本使用,更多细节,敬请期待。下期,我们介绍GUI中资源文件的使用。