0

我正在尝试使用三个 QToolButtons 制作三个互斥的单选按钮(基本上;它们是子类)。我在设计器中将 Checkable 设置为true,现在有两个问题:

  1. 它们需要相互排斥,即单击一个按钮应取消选中所有其他按钮。
  2. 始终只选中一个按钮。

第一个很容易通过以下连接到的插槽代码解决toggled(bool)

void Foo::slot_radio1(bool on) {
    if (on) {
        tb_radio2->setChecked(false);
        tb_radio3->setChecked(false);
    }
}

其他两个按钮也是如此。不好,但有效。第二个有点棘手,这就是我的问题发挥作用的地方。

在大多数 GUI 工具包中,如果需要,您可以在事件处理程序中取消事件,如果当前活动的按钮将被关闭,则可以在此处使用它来取消切换。但是,这适用于使用事件处理程序并传递可以修改的事件对象的系统。据我所知,使用信号/插槽,您是在事后处理事件并且对它们没有影响。除了您无论如何都无权访问事件数据的问题之外。我尝试过的天真但愚蠢的方法是

if (!on) {
    tb_radio1->setChecked(true);
}

基本上是在未选中时重新检查按钮 - 这会导致堆栈溢出,因为它会递归地再次触发每个其他插槽,一次又一次,...

通常是否有一种很好且干净的方法来实现这一目标?我宁愿不断开插槽,更改状态并再次连接它们。对于使用 Qt 多年的任何人来说,我可能会遗漏一些明显或微不足道的东西,但我想那不是我,因此它躲避了我。


现在有点乱了,但根据blockSignalsTim 和 Andreas 的建议,它可以工作:

void WinPhoenix::slot_radio1(bool on) {
    if (on) {
        bool before2 = radio2->blockSignals(true);
        bool before3 = radio3->blockSignals(true);
        radio2->setChecked(false);
        radio3->setChecked(false);
        radio2->blockSignals(before2);
        radio3->blockSignals(before3);
    } else {
        bool before = radio1->blockSignals(true);
        radio1->setChecked(true);
        radio1->blockSignals(before);
    }
}
4

1 回答 1

2

我宁愿不断开插槽,更改状态并再次连接它们。

您可以使用QObject::blockSignals()暂时禁用对象发送的信号:

bool before = tb_radio1->blockSignals(true);
tb_radio1->setChecked(true);
tb_radio1->blockSignals(before);

除此之外,您可以考虑使用QActionGroup()来实现互斥。

于 2013-01-23T15:26:48.523 回答