强制Qt QCheckBox在setChecked时发出信号

7
如果我调用QCheckBox::setChecked(x),只有在x与当前复选框状态不同时才会发出toggled信号。我理解这背后的逻辑是为了避免在没有变化时发出信号。然而,在某些情况下,当我有更复杂的小部件设置时,我需要始终发出信号。这可以确保连接到复选框的任何人都会收到第一个状态。
是否有一种方法使QCheckBox::setChecked(bool)无论状态是否改变都发出信号?
我的简单解决方法现在是通过执行setChecked(!x)setChecked(x)来强制复选框进入多个状态。我希望有更正确的方法来实现这一点。
4个回答

6

在查看QAbstractButton的实现时,我发现以下代码:

if (!d->checkable || d->checked == checked) {
    if (!d->blockRefresh)
        checkStateSet();
    return;
}

其中checkStateSet是虚函数。QCheckBox会覆盖这个函数,仅在状态改变时发出stateChanged()信号。d->blockRefresh如果您直接调用QCheckBox::setChecked( ... ),则可能设置为false,但我还没有测试过。

如果是这种情况,则意味着您可以子类化QCheckBox并将checkStateSet()方法重写为以下内容:

void MyCheckBox::checkStateSet()
{
    QCheckBox::checkStateSet();
    if( m_oldState == checkState() )
    {
        // emit the signal here, as QCheckBox::checkStateSet() didn't do it.
        emit stateChanged( m_oldState );
    }
    else
    {
        // don't emit the signal as it has been emitted already,
        // but save the old state
        m_oldState = checkState();
    }
}

这里的头文件包含

private:
    Qt::CheckState m_oldState;

在构造函数中,必须将其初始化为Qt::Unchecked


1
这可能能够解决问题,但是为了这个原因而进行子类化有一些棘手:你必须在设计器中记得升级,所有程序员都必须记得使用这个类。 - edA-qa mort-ora-y

2
这里有另一个解决方案,可能适用于您的情况,也可能不适用:
如果您可以确保在复选框有机会改变其状态之前将信号和槽连接起来,那么每个连接的类都可以安全地初始化自身,假设复选框未被选中。这是因为复选框在构造时始终未被选中。 这样一来,在连接信号后,您可能无需调用setChecked()。
但是,如果存在信号在复选框已经更改后才被连接的可能性,则此方法不起作用。我自己并不完全喜欢这种方法,但它可能仍然是您的选择之一。

0
一种方法是子类化 QCheckBox 并在其中实现需要的信号发射,例如:
class MyCheckBox : public QCheckBox
{
   Q_OBJECT
public:
   MyCheckBox(QWidget *parent = 0) : QCheckBox(parent) {};

   virtual void setChecked(bool checked) {
            QCheckBox::setChecked(checked); emit checkWasSet(checked);
            };
signals:
   void checkWasSet(bool value);

};

现在使用这个类来代替常规的QCheckBox类,你可以连接到checkWasSet()信号,以便在复选框状态被设置时进行操作。

根据文档,QAbstractButton中的setChecked不是虚函数。此外,我希望机制是通用的,适用于任何设置状态的方式。我还必须为几个其他类重复这种模式(这里只是以QCheckBox为例)。 - edA-qa mort-ora-y

0
你可以自己发射带有当前状态的信号:
checkbox.stateChanged.emit(checkbox.checkState())

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接