PyQt5 连接信号与自定义槽函数,解决槽函数重复执行的问题

目录

问题描述

错误原因 

解决方案

方案1. 修改函数名,通过connect()连接信号与槽

方案2. 自动连接信号与槽


背景:基于Python开发,使用Qt designer进行GUI设计。为了让业务逻辑与UI分离,不使用Qt designer中的信号/槽编辑器,而是用connect()函数连接信号与槽。

问题描述

我在窗体中添加一个PushButton类型按钮,名称是btnTest。然后def定义一个函数,命名为on_btnTest_clicked,并使用connect连接clicked信号与这个自定义槽函数。

结果点击按钮,槽函数中的处理重复执行了3遍。不符合预期。

PyQt5 连接信号与自定义槽函数,解决槽函数重复执行的问题_第1张图片

发生问题的代码模型简化如下:

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种,对应的代码修改方式不同。

方案1. 修改函数名,通过connect()连接信号与槽

自定义函数的名字,不要按照on_objectname_signalname的规则来命名。

修改以下2处,能够解决槽函数重复执行的问题。

PyQt5 连接信号与自定义槽函数,解决槽函数重复执行的问题_第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_())

方案2. 自动连接信号与槽

如果要建立信号和槽之间的自动连接,可以按照以下方式修改代码。

(1)设置控件名;

(2)QtCore.QMetaObject.connectSlotsByName;

(3)槽函数按照on_控件名_信号的规则来命名;

(4)添加@pyqtSlot()来定义函数为槽函数。

PyQt5 连接信号与自定义槽函数,解决槽函数重复执行的问题_第3张图片

完整代码如下:

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

你可能感兴趣的:(Python学习,qt,python,开发语言)