[Solved] Text changing checkable QPushButtons - Or - How to detect when value has changed.



  • So I'm trying to subclass QPushButton to change the text of a button depending on what checkable state the button is in. I've gotten it working when the button is clicked but am struggling to handle the situation where the button state is set from a DataWidgetMapper.

    It should do the following:

    1. When a row is selected and the mapper tells the button the boolean value, it should change the text to reflect that value (e.g. "Enabled" or "Disabled").
    2. When clicked, the button text should update as well as the state.

    EnabledButton.h
    @#include <QApplication>
    #include <QPushButton>

    class EnabledButton : public QPushButton
    {
    Q_OBJECT

    public:
    EnabledButton(QWidget * parent = 0) : QPushButton(parent){
    setText(tr("Disabled"));
    };

    Q_PROPERTY(bool checked MEMBER _checked WRITE setCheckedVal)

    bool _checked;

    void mouseReleaseEvent(QMouseEvent * e);

    void setCheckedVal(bool checked);
    };@

    EnabledButton.cpp
    @#include "EnabledButton.h"

    void EnabledButton::mouseReleaseEvent(QMouseEvent * e)
    {
    QPushButton::mouseReleaseEvent(e);
    if(isChecked())
    setText(tr("Enabled"));
    else
    setText(tr("Disabled"));
    }

    void EnabledButton::setCheckedVal(bool checked)
    {
    if(checked)
    setText(tr("Enabled"));
    else
    setText(tr("Disabled"));
    _checked = checked;
    }@

    Obviously overwriting the "checked" property is hugely less than ideal - i'm circumventing the basic button handling which leads it to lose track of it's value. I've tried to look into event filtering, but no events are jumping out at me as "Value changed".

    What's the right path to pursue here?



  • I am fairly new to Qt so I may not provide the best solutions but I have dealt with similar issues in my own application (though I don't really use properties all that much).

    I basically kept track of the state using my own variable but that was because my new "checked" state was more complex than the one in the base class. What about connecting to the clicked, pressed, or toggled signals within your own class? I have done that in some of my subclasses (including my new "checked' state class) with success. Or perhaps I am misunderstanding your problem.



  • The problem isn't that I'm not handling the click event properly - the issue is that I'm trying to find a way to detect the DataWidgetMapper setting the checked or value property.


  • Lifetime Qt Champion

    Hi,

    Why not use the checkable property from QPushButton ?



  • I'm already using checkable - but the visual distinction isn't sufficient for my use case. I'm trying to combine the checkable property with text change to more clearly show the state.

    For example, if the button is in a non-active (unpressed) state it will still show the text "Enabled" which seems likely to cause confusion.


  • Lifetime Qt Champion

    Enabled alone might be insufficient. What use case do you have that the checked button state is visually insufficient ?

    Anyway to change text properly:
    @
    MyWidget::MyWidget(QWidget *parent):
    QWidget(parent),
    button(new QPushButton)
    {
    button->setCheckable(true);
    connect(button, SIGNAL(toggled(bool)), this, SLOT(updateButtonText(bool)));
    updateButtonText(button->isChecked());
    }

    void MyClass::updateButtonText(bool checked)
    {
    if (checked) {
    button->setText(tr("My Button Checked"));
    } else {
    button->setText(tr("My Button Unchecked"));
    }
    }
    @



  • Thanks SGaist, I was fairly certain I was overthinking this - I ended up solving the problem by doing

    @connect(this, SIGNAL(toggled(bool)), this, SLOT(setChecked(bool)));@

    in my class constructor and then overriding setChecked to change the button text.

    I believe the problem I was having initially was in trying to override toggle() rather than setChecked(bool)

    Thanks again!


  • Lifetime Qt Champion

    That connection is wrong on several levels: setChecked is not virtual so you can't reimplement it like that and toggled and setChecked already work together in the original class.

    If you really want to do the text change inside your button class, use another slot like updateButtonText. That will have the advantage of also making your code clearer to understand.



  • Your point is well taken. I've changed the method name and everything is working perfectly. Thanks again for pointing me in the right direction.


  • Lifetime Qt Champion

    You're welcome !

    Now that you have your button working, please update the thread title prepending [solved] so other forum users may know a solution has been found :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.