Qt - 连接动态创建的小部件的信号

Qt - connect signals of dynamical created widgets

我有一个带参数的函数列表。对于每个参数,我都创建了一个保存其值的旋转框。有些函数的参数为​​零,有些函数的参数为​​ n>1。

代码看起来像这样(简化)

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
}

但是插槽需要知道调用了哪些小部件、参数名称及其值。然而,该信号仅提供一个值。

插槽看起来像这样

OnAmplitudeParameterChanged(int index, QString name, double value)

这在 Qt 中是如何解决的?我找到了 QSignalMapper class,但没有找到它如何解决我的问题。

我会为此使用一点 lambda

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

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


编辑

Jon Harper 的回答启发我使用 QObject::setProperty() 作为另一个有趣的解决方案:

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

然后在你的位置:

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

但无论如何,我可能还是会使用 lambda。

您可以使用QObject::sender()在插槽函数中获取调用者旋转框。

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

要扩展 Wiki Wang 的答案,请结合使用 sender()qobject_cast 和旋转框的对象名称:

在您的代码中:

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

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

然后在插槽中:

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
    }
}