首页 > 解决方案 > pyqt 按钮自动绑定到 on_..._clicked 函数,无需连接或 pyqtSlot

问题描述

我已经使用 pyqt5 和 qt-designer 几个星期了。我习惯于使用连接语句将信号连接到处理函数。

昨天我做了一段代码,它也自动将按钮单击信号连接到没有 pyqtSlot 装饰器的处理函数。

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

谁能解释为什么在没有连接或 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>

标签: pythonpyqtpyqt5qt-designer

解决方案


为什么要自动连接?

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)带有 objectname 的 pushButton "pushButton"

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

有一个信号叫clicked.

为什么你两次调用相同的方法?

QPushButton 有一个被重载的 clicked 信号,也就是说有几个同名但参数不同的信号。如果审查了文档:

void QAbstractButton::clicked(bool checked = false)

虽然理解起来可能比较复杂,上面的代码相当于:

clicked = pyqtSignal([], [bool])

这类似于:

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

所以总而言之 QPushButton 有 2 个 clicked 信号将连接到 on_pushButton_clicked 函数,所以当你按下按钮时,两个信号将通过调用相同的方法发出,这样 clicked 将被打印 2 次。


如果上一个信号是用相同的方法连接的,则连接不考虑,因此使用手动连接将有 3 个连接(其中 2 个信号在没有参数的情况下单击 [1 个自动,另一个手动],1 个信号被单击参数),因此该方法将被调用 3 次。

当您使用装饰器时@pyqtSlot,您正在指示签名(即参数的类型),因此 connect 方法只会与与插槽签名匹配的信号建立连接,因此您不再看到问题,因为您使用了信号 no论据


推荐阅读