如何断言 PyQt5 信号的身份?

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


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

如图所示,分别涉及==、is和的三个比较id()都产生False,即它们不能断言左手和右手参数的同一性。


有没有办法断言widget.clicked并signal引用相同的信号?


慕哥9229398
浏览 204回答 2
2回答

慕斯王

每次调用时都会创建作为实体的信号,因为它们代表不同的连接:In [1]: import sysIn [2]: from PyQt5 import QtWidgetsIn [3]: app = QtWidgets.QApplication(sys.argv)In [4]: button = QtWidgets.QPushButton()In [5]: id(button.clicked)Out[5]: 140150155639464In [6]: id(button.clicked)Out[6]: 140150154507528In [7]: id(button.clicked)Out[7]: 140150155640184In [8]: id(button.clicked)Out[8]: 140150155640504In [9]: id(button.clicked)Out[9]: 140150154510128In [10]: id(button.clicked)Out[10]: 140149427454320因此,如果在同一个信号和插槽之间连接 100 次,并且在发出信号时,该插槽将被调用 100 次:import sysfrom PyQt5 import QtCore, QtWidgetsdef 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_())输出:clickedclickedclickedclickedclickedclickedclickedclickedclickedclicked所以直接解决你的问题是不可能的,但我认为你的目标是区分哪个对象发出调用插槽的信号,因为你可能有几个对象连接到同一个插槽,如果有解决方案:一、使用sender()方法如果插槽属于 QObject(或从 QObject 派生的类作为小部件),那么您可以使用 sender 方法获取发出信号的对象。import sysfrom PyQt5 import QtCore, QtWidgetsclass 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 拉姆达函数import sysfrom PyQt5 import QtCore, QtWidgetsclass 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 函数import sysfrom PyQt5 import QtCore, QtWidgetsfrom functools import partialclass 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 方法

胡子哥哥

尝试一下:import sysfrom PyQt5.QtWidgets import QApplication, QPushButtonapp = QApplication([])def clickButton(w):&nbsp; &nbsp; # Check what you clicked here.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # <-----&nbsp; &nbsp; return print(w.text())widget&nbsp; = QPushButton('Button 1')widget.clicked.connect(lambda : clickButton(widget))widget2 = QPushButton('Button 2')widget2.clicked.connect(lambda : clickButton(widget2))widget.setGeometry(300, 150, 100, 100)widget.show()widget2.setGeometry(450, 150, 100, 100)widget2.show()sys.exit(app.exec_())
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python