Doğukan Tunç
Doğukan Tunç

Reputation: 347

Changing the behavior of a widget type in another class

I have a MainWindow class in Qt, in which several checkable QGroupBox widgets are placed.

What I want to do is, to trigger a general onClick(bool checked) slot whenever one (any) of the QGroupBox objects are clicked, identify the sender and trigger some code.

I need to capture the objects' "clicked" signal in order to prevent a disabling action it performs on its children when the control is clicked.

This is the signal I'm trying to handle:

class Q_WIDGETS_EXPORT QGroupBox : public QWidget
{
    ...
    Q_SIGNALS:
        void clicked(bool checked = false);
    ...
};

I tried adding a custom slot like this and tried connecting it with the signal above but since QGroupBox at its own is not an object or pointer, the operation fails.

void MainWindow::onClick(bool clicked)
{
    qDebug()<<"Custom slot triggered";
}

Long story short, I need to handle a control type's default behavior within my MainWindow class.

Thanks for any ideas in advance.

Upvotes: 0

Views: 195

Answers (2)

Doğukan Tun&#231;
Doğukan Tun&#231;

Reputation: 347

@Kuba Ober, maybe you're right, I could not state my problem and the facts around it seperately and clearly. Thank you for pointing that out.

After checking out the QGroupBox class' source, I discovered that a "toggle" signal is emitted after every other operation in a "clicked" event.

http://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/widgets/qgroupbox.cpp

void QGroupBox::setChecked(bool b)
{
    Q_D(QGroupBox);
    if (d->checkable && b != d->checked) {
        update();
        d->checked = b;
        d->_q_setChildrenEnabled(b);
#ifndef QT_NO_ACCESSIBILITY
        QAccessible::State st;
        st.checked = true;
        QAccessibleStateChangeEvent e(this, st);
        QAccessible::updateAccessibility(&e);
#endif
        emit toggled(b);
    }
}

By combining this information with that of @rbaleksandar 's suggestion, I managed to obtain a solution.

I iterated through the controls of my MainWindow class and connected every QGroupBox's "toggle" signal with a common "MainWindow::onToggle" slot in which I could handle the post-event operations I desire.

As for my previous approach, I could've created a class which inherits QGroupBox and override any methods I wish to. But that would be overkill compared to my current solution. The fix I've came up with did the trick perfectly.

Thanks everyone for their insight and help.

Upvotes: 0

I need to capture the objects' "clicked" signal in order to prevent a disabling action it performs on its children when the control is clicked.

Perhaps, but I'm smelling an XY Problem here. You can certainly prevent emission of signals by invoking blockSignals() on the widget. But that's a hack - it will also prevent Qt's internals from acting on the object's destroyed() signal, and you might subtly break other users of the object's signals.

Instead, one could make the UI stateful and have the controller implement the stateful aspect of the button's interaction with the rest of the application. Currently, the button's clicked() signal is connected directly to other users. Instead, connect the button to the controller, and have the controller disable the children only when it's appropriate to do so. One could use the QStateMachine to make this stateful behavior explicit in terms of states.

Upvotes: 2

Related Questions