Matthias Pospiech
Matthias Pospiech

Reputation: 3494

Qt - connect signals of dynamical created widgets

I have a list of functions with parameters. For each parameter I create a spinbox holding its value. Some functions have zero parameters others have n>1 parameters.

The code looks like this (simplified)

for (int i = 0; i < parameterList.size(); ++i) {

    QString valueName = parameterList().at(i);
    double value = parameter(valueName);

    QDoubleSpinBox * spinbox = new QDoubleSpinBox();
    QLabel * label = new QLabel();
    label->setText(valueName);
    spinbox->setValue(value);

    // does NOT work, Slot need three parameters!
    QObject::connect(spinbox, &QDoubleSpinBox::valueChanged,
                        this,  &OnAmplitudeParameterChanged);

    ... add widgets to layout
}

However the slot needs to know which widgets was calling, the parameter name and its value. The signal however provides only a value.

The slot looks like this

OnAmplitudeParameterChanged(int index, QString name, double value)

How is this solved in Qt? I found a QSignalMapper class but not how this would solve my problem.

Upvotes: 1

Views: 321

Answers (3)

jonspaceharper
jonspaceharper

Reputation: 4347

To expand on Wiki Wang's answer, use the combination of sender(), qobject_cast and the spinbox's object name:

In your code:

QString valueName = parameterList().at(i);
double value = parameter(valueName);

QDoubleSpinBox * spinbox = new QDoubleSpinBox();
spinbox->setObjectName(valueName);

Then in the slot:

void SomeClass::OnAmplitudeParameterChanged(double value)
{
    QDoubleSpinBox *spinbox = qobject_cast<QDoubleSpinBox *>(sender());
    if (spinbox && parameterList.contains(spinbox->objectName()) {
        int value = parameter(spinbox->objectName());
        // your code here
    }
}

Upvotes: 1

Tomas
Tomas

Reputation: 2210

I would use a little lambda for that

auto func = [i, valueName, this](double value){
    OnAmplitudeParameterChanged(i, valueName, value);
};

QObject::connect(spinbox, &QDoubleSpinBox::valueChanged, func);


EDIT

Jon Harper's answer inspired me to use the QObject::setProperty() as another interesting solution:

QDoubleSpinBox* spinbox = new QDoubleSpinBox();
spinbox->setProperty("myindex", i);
spinbox->setProperty("myname", valueName);

and then in your slot:

void SomeClass::OnAmplitudeParameterChanged(double value)
{    
    int index = sender()->property("myindex").toInt();
    QString name = sender()->property("myname").toString();
}

But still, I would probably use the lambda anyway.

Upvotes: 3

Wiki Wang
Wiki Wang

Reputation: 698

You can use QObject::sender() to get the caller spinbox in the slot function.

QDoubleSpinBox *spinbox = static_cast<QDoubleSpinBox *>(QObject::sender());

Upvotes: 1

Related Questions