如何断言 PyQt5 信号的身份? [英] How do I assert the identity of a PyQt5 signal?

查看:43
本文介绍了如何断言 PyQt5 信号的身份?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想断言 PyQt5 信号的身份.具体来说,我想检查来自给定 QPushButton 对象的 clicked 信号是否与存储在名为 signal 的变量中的信号相同.以下代码段说明了这种情况:

I'm in a situation where I want to assert the identity of a PyQt5 signal. Specifically, I want to check whether the clicked signal from a given QPushButton object is identical to a signal that is stored in a variable named signal. The following snippet illustrates the situation:

from PyQt5.QtWidgets import QApplication, QPushButton

app = QApplication([])
widget = QPushButton()
signal = widget.clicked

widget.clicked == signal
Out[1]: False

widget.clicked is signal
Out[2]: False

id(widget.clicked) == id(signal)
Out[3]: False

如图所示,分别涉及==isid()的三个比较都产生False>,即他们无法断言左手和右手参数的同一性.

As shown, the three comparisons involving ==, is, and id() respectively all produce False, i.e. they fail to assert the identity of the left-hand and the right-hand argument.

有什么方法可以断言 widget.clickedsignal 引用的是同一个信号?

Is there any way to assert that widget.clicked and signal are referencing the same signal?

推荐答案

每次调用时都会创建作为实体的信号,因为它们代表不同的连接:

Signals as entities are created each time you invoke it as they represent a different connection:

In [1]: import sys

In [2]: from PyQt5 import QtWidgets

In [3]: app = QtWidgets.QApplication(sys.argv)

In [4]: button = QtWidgets.QPushButton()

In [5]: id(button.clicked)
Out[5]: 140150155639464

In [6]: id(button.clicked)
Out[6]: 140150154507528

In [7]: id(button.clicked)
Out[7]: 140150155640184

In [8]: id(button.clicked)
Out[8]: 140150155640504

In [9]: id(button.clicked)
Out[9]: 140150154510128

In [10]: id(button.clicked)
Out[10]: 140149427454320

因此,如果在同一个信号和插槽之间连接 100 次,并且在发出信号时,该插槽将被调用 100 次:

Therefore if you connect 100 times between the same signal and slot, and when the signal is emitted, the slot will be called 100 times:

import sys
from PyQt5 import QtCore, QtWidgets

def foo():
    print("clicked")

if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    button = QtWidgets.QPushButton("Press me")
    button.show()
    for _ in range(10):
        button.clicked.connect(foo)
    # the click is emulated
    QtCore.QTimer.singleShot(1000, lambda: button.animateClick(500))
    QtCore.QTimer.singleShot(2000, app.quit)
    sys.exit(app.exec_())

输出:

clicked
clicked
clicked
clicked
clicked
clicked
clicked
clicked
clicked
clicked

所以直接解决你的问题是不可能的,但我认为你的目标是区分哪个对象发出调用插槽的信号,因为你可能有几个对象连接到同一个插槽,如果有一个解决方案:

So it will be impossible to solve your problem directly but I think that your goal is to discriminate which object that emitted the signal that calls the slot since you probably have several objects connected to the same slot, and for that if there is a solution:

如果插槽属于 QObject(或从 QObject 派生的类作为小部件),那么您可以使用 sender 方法获取发出信号的对象.

If the slot belongs to a QObject (or classes derived from QObject as the widgets) then you can use the sender method to obtain the object that emitted the signal.

import sys
from PyQt5 import QtCore, QtWidgets

class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)

        self.button_1 = QtWidgets.QPushButton("button 1")
        self.button_1.clicked.connect(self.foo)
        self.button_2 = QtWidgets.QPushButton("button 2")
        self.button_2.clicked.connect(self.foo)
        self.button_3 = QtWidgets.QPushButton("button 3")
        self.button_3.clicked.connect(self.foo)

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.button_1)
        lay.addWidget(self.button_2)
        lay.addWidget(self.button_3)

    @QtCore.pyqtSlot()
    def foo(self):
        button = self.sender()
        if button is self.button_1:
            print("button_1")
        elif button is self.button_2:
            print("button_2")
        elif button is self.button_3:
            print("button_3")

if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

2.将对象作为附加参数传递

2.1 拉姆达函数<小时>

2. Pass the object as an additional parameter

2.1 lambda function

import sys
from PyQt5 import QtCore, QtWidgets

class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)

        self.button_1 = QtWidgets.QPushButton("button 1")
        self.button_1.clicked.connect(lambda *args, b=self.button_1 : self.foo(b))
        self.button_2 = QtWidgets.QPushButton("button 2")
        self.button_2.clicked.connect(lambda *args, b=self.button_2 : self.foo(b))
        self.button_3 = QtWidgets.QPushButton("button 3")
        self.button_3.clicked.connect(lambda *args, b=self.button_3 : self.foo(b))

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.button_1)
        lay.addWidget(self.button_2)
        lay.addWidget(self.button_3)

    def foo(self, button):
        if button is self.button_1:
            print("button_1")
        elif button is self.button_2:
            print("button_2")
        elif button is self.button_3:
            print("button_3")

if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

2.1 functools.partial 函数<小时>

2.1 functools.partial function


import sys
from PyQt5 import QtCore, QtWidgets
from functools import partial

class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)

        self.button_1 = QtWidgets.QPushButton("button 1")
        self.button_1.clicked.connect(partial(self.foo, self.button_1))
        self.button_2 = QtWidgets.QPushButton("button 2")
        self.button_2.clicked.connect(partial(self.foo, self.button_2))
        self.button_3 = QtWidgets.QPushButton("button 3")
        self.button_3.clicked.connect(partial(self.foo, self.button_3))

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.button_1)
        lay.addWidget(self.button_2)
        lay.addWidget(self.button_3)

    def foo(self, button):
        if button is self.button_1:
            print("button_1")
        elif button is self.button_2:
            print("button_2")
        elif button is self.button_3:
            print("button_3")

if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

<小时>

在我的情况下,如果可以使用,我更喜欢使用 sender,然后是 functools.partial,最后是 lambda 方法


In my case I prefer to use sender if I can use it, then functools.partial and finally lambda methods

这篇关于如何断言 PyQt5 信号的身份?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆