pyqt按钮自动绑定到on _..._ clicked函数,无需连接或pyqtSlot

时间:2019-02-25 07:18:59

标签: python pyqt pyqt5 qt-designer

我已经将pyqt5与qt-designer一起使用了几周了。我习惯用connect语句将信号连接到处理函数。

昨天我编写了一段代码,该代码还自动将按钮单击的信号连接到没有pyqtSlot装饰器的处理程序函数。

  • 将单击的信号连接到功能上时,单击一次按钮将导致该功能执行三次。

  • 一次单击一次按钮,删除connect语句会使函数执行两次。

  • 在函数中添加@pyqtSlot可以正常执行一次。

  • 将处理程序函数重命名为“ on_ 按钮名称 _clicked”以外的其他名称也可以正常执行一次。

以下代码显示了这种“自动连接”行为。

谁能解释为什么在没有连接或pyqtSlot的情况下会发生这种带有双重处理程序的自动连接吗?

谢谢,梅斯

from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QMainWindow
from PyQt5.uic import loadUi
import sys

class MainWindow(QMainWindow):

    def __init__(self):

        super().__init__()

        loadUi('MainWindowTestButton.ui', self)
        self.show()

    def on_pushButton_clicked(self):
        print('clicked')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MainWindow()
    sys.exit(app.exec_())

上面的代码打印

点击

点击

单击一个按钮时。

这是示例中的MainWindowTestButton.ui文件

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindowTestButton</class>
 <widget class="QMainWindow" name="MainWindowTestButton">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QPushButton" name="pushButton">
    <property name="geometry">
     <rect>
      <x>70</x>
      <y>60</y>
      <width>75</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>PushButton</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

1 个答案:

答案 0 :(得分:3)

为什么要自动连接?

loadUi()函数在内部调用connectSlotsByName()方法,如果某些方法具有以下结构,则会自动建立连接:

C ++:

void on_<object name>_<signal name>(<signal parameters>);

Python:

def on_<object name>_<signal name>(<signal parameters>):

在您的情况下,on_pushButton_clicked方法满足该要求,因为您有一个QWidget(从QObject继承)按钮,其对象名为"pushButton"

<widget class="QPushButton" name="pushButton">

具有称为clicked的信号。

为什么要两次调用同一方法?

QPushButton包含一个单击的信号,该信号已重载,也就是说,存在多个具有相同名称但参数不同的信号。如果the docs被审核:

void QAbstractButton::clicked(bool checked = false)

虽然理解上面的代码可能会很复杂,但它等同于:

clicked = pyqtSignal([], [bool])

这类似于:

clicked = pyqtSignal()
clicked = pyqtSignal([bool])

因此,总而言之,QPushButton具有2个单击信号,这些信号将连接到on_pushButton_clicked函数,因此,当您按下按钮时,两个信号都将通过调用两种相同的方法而发出,从而将单击信号打印两次。


如果以前的信号是用相同的方法连接的,则不会考虑连接,因此,在您的手动连接中,将有3个连接(点击的信号中有2个不带参数[1个自动,另一个为手动]和1个带参数的)。信号点击带有参数),因此该方法将被调用3次。

在使用装饰器@pyqtSlot时,您要指示签名(即参数的类型),因此connect方法将仅使用与插槽签名匹配的信号进行连接,因此看不到不再出现问题,因为您使用信号没有参数