Search code examples
c++qtsignals

Qt How can I get a signal from int when the value changes?


So lets say I a QDialog class like this

class DiagExample : public QDialog
{
    Q_OBJECT

public:
    DiagExample(QWidget *parent);

private:
    int myIntValue = 0;

    QPushButton *AddToValue;
    QPushButton *MinusToValue;
    QLabel *counter;

};

And the implementation looks like this

DiagExample::DiagExample(QWidget *parent) : QDialog(parent)
{
    setWindowTitle("Example Diag");

    QVBoxLayout *layout = new QVBoxLayout(this);
   
    AddToValue = new QPushButton(tr("Add"));
    MinusToValue = new QPushButton(tr("Minus"));
    counter = new QLabel;

    connect(AddToValue, &QPushButton::released, [=](){myIntValue++;});
    connect(MinusToValue, &QPushButton::released, [=](){myIntValue--;});

    layout->addWidget(AddToValue);
    layout->addWidget(MinusToValue);
    layout->addWidget(counter);

    // below is what I want to achieve but have no idea how
    // essentially when value of the int is changed, text of
    // counter (QLabel) will be set to the new value

    connect(myIntValue, ???, [=](int newValue){ 
        counter->setText(QString::number(newValue);});
}

I know that I could go straight from QPushButton::released -> setText on the QLabel, but my code will eventually have many inputs feeding into the counter, so from a point of readability and simplicity, I would rather have this sort of paradigm --- INPUT_WIDGET -> myIntValue -> setText(NEW VALUE OF myIntValue).


Solution

  • Standard way of doing such things in Qt:

    class DiagExample : public QDialog
    {
        Q_OBJECT
    
        Q_PROPERTY(intValue READ intValue NOTIFY onIntValueChange)
    
    public:
        DiagExample(QWidget *parent);
    
        int intValue() const;
    
    signals:
        void onIntValueChange(int);
    
    private:
        int myIntValue = 0;
    
        QPushButton *AddToValue;
        QPushButton *MinusToValue;
        QLabel *counter;
    };
    

    Now in cpp:

    DiagExample::DiagExample(QWidget *parent) : QDialog(parent)
    {
        setWindowTitle("Example Diag");
    
        QVBoxLayout *layout = new QVBoxLayout(this);
       
        AddToValue = new QPushButton(tr("Add"));
        MinusToValue = new QPushButton(tr("Minus"));
        counter = new QLabel;
    
        connect(AddToValue, &QPushButton::released, [=](){
           myIntValue++;
           emit onIntValueChange(myIntValue);
        });
        connect(MinusToValue, &QPushButton::released, [=](){
           myIntValue--;
           emit onIntValueChange(myIntValue);
        });
    
        layout->addWidget(AddToValue);
        layout->addWidget(MinusToValue);
        layout->addWidget(counter);
    
        // below is what I want to achieve but have no idea how
        // essentially when value of the int is changed, text of
        // counter (QLabel) will be set to the new value
    
        connect(this, &DiagExample::onIntValueChange, [=](int newValue){ 
            counter->setText(QString::number(newValue);});
    }
    
    int DiagExample::intValue() const {
        return myIntValue;
    }
    

    Note only QObject can emit signals!