2016-08-12 3 views
1

Ich habe eine Liste von Funktionen mit Parametern. Für jeden Parameter erstelle ich eine Spinbox mit ihrem Wert. Einige Funktionen haben keine Parameter, andere haben n> 1 Parameter.Qt - verbinden Signale von dynamisch erstellten Widgets

Der Code sieht wie folgt aus (vereinfacht)

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 
} 

jedoch der Schlitz wissen muss, welche Widgets anrufen, den Parameternamen und seinen Wert. Das Signal liefert jedoch nur einen Wert.

Der Schlitz sieht wie folgt aus

OnAmplitudeParameterChanged(int index, QString name, double value) 

Wie dies in Qt gelöst? Ich habe eine QSignalMapper-Klasse gefunden, aber nicht, wie dies mein Problem lösen würde.

Antwort

1

Um auf Wiki Wangs Antwort zu erweitern, verwenden Sie die Kombination von sender(), qobject_cast und den Objektnamen des Spinnbox:

In Ihrem Code:

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

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

Dann in den Schlitz:

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

Es kompiliert nicht 'QDoubleSpinBox * spinbox = qobject_cast (QObject :: sender());' gibt mir den Fehler 'error: kann 'QDoubleSpinBox' nicht in 'QDoubleSpinBox *' in Initialisierung konvertieren –

+0

@MatthiasPospiech Whoops. Das sollte '' sein. Ich habe die Antwort ebenfalls korrigiert. –

3

Ich würde verwenden, um ein wenig Lambda für das

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

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


EDIT

Jon Harper Antwort mich inspiriert die QObject::setProperty() als eine weitere interessante Lösung zu verwenden:

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

und dann in Ihrem Steckplatz:

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

Aber trotzdem würde ich wahrscheinlich das Lambda sowieso verwenden.

+0

Können Sie ein ausführlicheres Beispiel für Lambda liefern? Die Funktion ist nur innerhalb der Funktion verfügbar, die die Verbindung definiert. Auch die Parameter sind nur dort bekannt. Ich verstehe also nicht, wie das funktionieren soll. –

+0

@Matthias Das 'func' ist ein ** Funktionsobjekt **, das mit Hilfe eines Lambda-Ausdrucks erstellt wird. Es hat alle notwendigen Parameter gespeichert (die innerhalb der ** Lambda Capture-Liste **) und die 'connect()' Methode erstellt eine Kopie davon für späteren Aufruf. Ich hoffe es ergibt einen Sinn für dich. – Tomas

+0

Nur eine Anmerkung: anstelle von 'auto func = ...' könnte es auch sein 'std :: function func = ...' – Tomas

1

Sie können QObject::sender() verwenden, um die Drehscheibe des Aufrufers in der Slot-Funktion zu erhalten.

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

Hinweis: 'qobject_cast' ist sicherer und bevorzugt. –