阻塞Qt中禁用部件的信号

Blocking signals on disabled widgets in Qt

本文关键字:信号 用部 Qt 阻塞      更新时间:2023-10-16

我有一个禁用的组合,但添加一个元素将发出currentIndexChanged(int)信号。

我希望当一个小部件被禁用时,信号会自然关闭,但事实并非如此。我知道有blockSignals(bool),但如果有许多小部件的信号必须"禁用时阻塞",blockSignals将需要每个小部件的布尔状态。

当一个小部件被禁用时,我如何禁用它发送的信号(而不改变它的blockSignals状态)?

编辑澄清一下:由于这是一个小部件,当它被禁用时,用户不能与它交互,但是当以编程方式更改小部件时,会发出一些信号。在我的例子中,有两个有趣的信号:currentIndexChanged(int)activated(int)

我的代码中的问题是,我有时以编程方式改变组合,我希望它发出一个信号,有时是用户通过交互改变组合。这就是为什么我使用currentIndexChanged而不是activated

无论如何,在这两种情况下,我都不希望在widget被禁用时发出信号。

如果你只有一个QComboBox,没有其他的,那么从最终用户的角度来看,QComboBox信号是基于用户交互的。

我根本无法重现这个问题。我刚刚编写了一个短程序,由于无法简单地与小部件交互,因此无法获得发出的任何QComboBox信号。

编辑:这可能是一个好主意更新你的问题与更多的上下文为休闲读者,但基于评论中的进一步澄清,是的,程序化它可能是这种情况,但然后信号可能是有用的程序化处理,同样,与相应的插槽,所以它不是一个重大的改进,如果Qt自动阻塞它们。

幸运的是,您希望拥有的特性已经可用:

bool QObject::blockSignals(bool block)

如果block为true,则该对象发出的信号被阻塞(即,发出信号将不会调用与之相连的任何东西)。如果block为false,则不会发生阻塞。

返回值是signalsBlocked()的前一个值。

请注意,即使该对象的信号被阻塞,也会发出destroy()信号。

如果您想为许多小部件这样做,请创建一个简单的函数,而不是调用myWidget->setDisabled(true);:

inline bool disableAndBlockSignals(QWidget *widget)
{ 
    widget->setDisabled(true);
    return widget->blockSignals(true);
}

如果您只想禁用其中的一些,例如currentIndexChanged,那么您可以手动使用disconnect

您可以在想要阻塞信号时断开QObject::disconnect();的信号,然后在想要解除阻塞时重新连接它们

在您的例子中,信号是传递给其他对象的状态信息的唯一来源。如果禁用它们,其他对象将永远不会收到状态更改的任何通知。这可能会导致依赖于小部件状态通知的对象出现错误。

至少有两个解:

  1. 不要改变小部件的状态。你当然可以推迟更新小部件的内容,直到它被重新启用。

  2. 创建一个代理来监视原始小部件的状态,并将信号(带压缩)排队,直到小部件重新启用。

由于这些变通方法,您的设计可能需要返工。如果你能处理那些被禁用的小部件发出的信号,也许会更好。您还应该评估禁用小部件是否不会破坏用户体验。如果用户想要查看小部件的内容,但又不想更改当前设置,该怎么办?在这种情况下,禁用小部件就太过分了。您可以创建自己的(也许是子类化的)小部件,使控件不被禁用,但当前元素保持固定。这甚至可以是一个单独的对象,适用于任何控件——通过明智地利用user属性。