【发布时间】:2014-08-10 09:36:51
【问题描述】:
我有几个按钮,每个按钮都有一个 Signal,每当单击按钮时都会发出它们的一个属性(例如,一个整数)。在父类中,我希望能够捕获任何按钮的发射并根据按钮的特定属性做出反应。
我可以想办法通过单独“连接”父类中的每个按钮来做到这一点,但这似乎是错误的,而且很麻烦,因为在我的应用程序中,我将添加和删除按钮作为功能的一部分。我可能想错了……还有建议吗?
【问题讨论】:
我有几个按钮,每个按钮都有一个 Signal,每当单击按钮时都会发出它们的一个属性(例如,一个整数)。在父类中,我希望能够捕获任何按钮的发射并根据按钮的特定属性做出反应。
我可以想办法通过单独“连接”父类中的每个按钮来做到这一点,但这似乎是错误的,而且很麻烦,因为在我的应用程序中,我将添加和删除按钮作为功能的一部分。我可能想错了……还有建议吗?
【问题讨论】:
你可以这样做:
from functools import partial
def buttonEvent(i):
print(i)
for i in range(5):
button = QtWidgets.QPushButton("Button: " + str(i))
button.clicked.connect(partial(buttonEvent, i))
在 Qt 中,您需要将信号连接到函数名称,您不能指定参数或任何内容。当涉及到许多独特的小部件或生成的小部件或诸如此类的东西时,这很烦人。两个不错的解决方案是使用部分和 lambda。当我想调用带有独立于变量的参数的函数时(例如button.clicked.connect(lambda: print("Button clicked"))),我使用 lambda。如果您的函数调用依赖于稍后将更改的某个变量,则需要使用 partial,这将立即保存变量内容。 Lambda 将等到被调用才能使用变量(因此,在上述情况下,如果使用了 lambda,则所有按钮都会打印“4”)。
【讨论】:
在 Qt 中,您可以将任何信号与任何插槽连接。这也意味着您可以将单个信号连接到多个插槽或将多个信号连接到单个插槽。
现在,如果每个按钮都做不同的事情并且数量不多,我会手动将每个按钮连接到不同的插槽,以便将它们很好地分开。
在您的情况下,您可能希望以自动方式将所有按钮与单个插槽连接,并在此插槽中通过 self.sender() 确定原始按钮,然后使用此信息进行操作。
例子:
每当您的小部件中出现新按钮时
new_button.clicked.connect(self.parent().buttons_clicked)
# always the same recipient
在父类中:
def buttons_clicked(self):
button = self.sender()
# do something useful depending on the button that sent the signal
这里缺少的是传输属性(数字或其他)的方式。你现在没有具体说明你是怎么做的,但它可能不应该通过连接到同一个插槽来显着改变。
edit:作为旁注,Qt 中也有大致相同的事件。 Signals/slots vs events 是一个有趣的讨论。根据您的问题(许多动态按钮)而不是连接和断开连接,您最好发送事件。
【讨论】: