我处于要断言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
引用的是同一信号?
答案 0 :(得分:2)
作为实体的信号会在您每次调用时创建,因为它们表示不同的连接:
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次:
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
因此不可能直接解决您的问题,但是我认为您的目标是区分哪个对象发出了调用插槽的信号,因为您可能有多个对象连接到同一个插槽,如果存在解决方案:
sender()
方法如果插槽属于QObject(或作为QWidget派生自QObject的类),则可以使用sender方法获取发出信号的对象。
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_())
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函数
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方法
答案 1 :(得分:0)
尝试一下:
import sys
from PyQt5.QtWidgets import QApplication, QPushButton
app = QApplication([])
def clickButton(w):
# Check what you clicked here. # <-----
return print(w.text())
widget = 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_())