目录
问题描述
错误原因
解决方案
方案1. 修改函数名,通过connect()连接信号与槽
方案2. 自动连接信号与槽
背景:基于Python开发,使用Qt designer进行GUI设计。为了让业务逻辑与UI分离,不使用Qt designer中的信号/槽编辑器,而是用connect()函数连接信号与槽。
我在窗体中添加一个PushButton类型按钮,名称是btnTest。然后def定义一个函数,命名为on_btnTest_clicked,并使用connect连接clicked信号与这个自定义槽函数。
结果点击按钮,槽函数中的处理重复执行了3遍。不符合预期。
发生问题的代码模型简化如下:
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)
# 连接按钮btnTest的内置信号clicked与自定义槽函数on_btnTest_clicked
btnTest1 = self.btnTest
btnTest1.clicked.connect(self.on_btnTest_clicked)
def on_btnTest_clicked(self):
# 需要在槽函数中做的处理
print('test button is clicked')
if __name__ == '__main__':
app = QApplication(sys.argv)
ui = MainWindow()
ui.show()
sys.exit(app.exec_())
如果函数以on_objectname_signalname的规则命名,会使得信号与槽自动连接。
在这个示例中,objectname指的是按钮btnTest,signalname是需要关联的信号名称clicked。我将函数命名为on_btnTest_clicked(),使得按钮与点击事件自动连接,又用connect连接,导致了处理的重复执行。
信号与槽的连接方式可以有connect()和自动连接2种,对应的代码修改方式不同。
自定义函数的名字,不要按照on_objectname_signalname的规则来命名。
修改以下2处,能够解决槽函数重复执行的问题。
修改后的完整代码如下:
import sys
from PyQt5.Qt import *
from PyQt5 import QtWidgets, QtCore
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)
# 连接btnTest的点击信号与自定义函数on_execute_test()
btnTest1 = self.btnTest
btnTest1.clicked.connect(self.on_execute_test)
def on_execute_test(self):
print('test button is clicked')
if __name__ == '__main__':
app = QApplication(sys.argv)
ui = MainWindow()
ui.show()
sys.exit(app.exec_())
如果要建立信号和槽之间的自动连接,可以按照以下方式修改代码。
(1)设置控件名;
(2)QtCore.QMetaObject.connectSlotsByName;
(3)槽函数按照on_控件名_信号的规则来命名;
(4)添加@pyqtSlot()来定义函数为槽函数。
完整代码如下:
import sys
from PyQt5.Qt import *
from PyQt5 import QtWidgets, QtCore
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)
self.btnTest.setObjectName("testbutton")
QtCore.QMetaObject.connectSlotsByName(self)
@QtCore.pyqtSlot()
def on_testbutton_clicked(self):
print('test button is clicked')
if __name__ == '__main__':
app = QApplication(sys.argv)
ui = MainWindow()
ui.show()
sys.exit(app.exec_())
方案2同样解决了槽函数重复执行的问题,但自动连接的实现方法对我来说比较陌生,第1种connect()方法对我来说更好理解,所以最终我用了方案1。
参考文章:
https://blog.csdn.net/hubing_hust/article/details/128198460
https://tool.4xseo.com/a/50298.html