2017-05-31 4 views
0

Ich versuche, eine Konfigurationsmenü-Box für eine Anwendung zu erstellen, und habe ein QDialog-Feld verwendet, um die Optionen anzuzeigen, die der Benutzer ändern kann. Diese Box enthält QComboBoxes und QLineEdits, aber viele davon (7 Kombinationsfelder und 12 Zeilenbearbeitungen). Es gibt einen QPushButton im unteren Bereich namens "Apply Changes", der nur aktiviert werden sollte, wenn eine Eigenschaft in der Box geändert wird.Kann ein Slot aufgerufen werden, wenn eines der Widgets in einem Dialogfeld ein Signal ausgibt?

Muss ich jedes Signal von jedem Widget mit einem Slot verbinden, um die Schaltfläche einzeln zu aktivieren, oder gibt es ein Signal, das die QDialog-Box selbst aussendet, wenn sich ihre Widgets ändern?

Im Moment habe ich dies:

connect(Combo1,SIGNAL(activated(QString)),this,SLOT(fnEnable(QString))); 
connect(Combo2,SIGNAL(activated(QString)),this,SLOT(fnEnable(QString))) 

durch 17 weitere Linien dieser Verbindungen gefolgt.

void MyClass::fnEnable(QString) 
{ 
ApplyButton->setEnabled(true); //It is initialised as false 
} 

Ich habe mich gefragt, ob es ein kürzerer Weg, dies zu tun war, vielleicht von QDialog emittieren ein Signal (wie bereits erwähnt)

dass

Ich weiß (ich nicht einen in den documentation finden konnte) das beschleunigt das Programm nicht, da nur die benötigte Verbindung aufgerufen wird, aber es würde weitere Versuche, ambitioniertere Dialoge zu erleichtern, erschweren.

+0

Eigentlich gibt es kein solches Signal, sondern ein Ansatz ist, eine Liste von QComboBox zu erstellen und machen die Verbindungen mit einem für zum Beispiel: 'QList <*QCombobox> l; l << combobox1 << combobox2 << ....; for (auto combo: l) {connect (kombiniert, SIGNAL (aktiviert (QString)), dies, SLOT (fnEnable (QString))} '. Das gleiche würde mit QLineEdit getan werden – eyllanesc

Antwort

3

Eigentlich gibt es kein solches Signal, sondern ein Ansatz ist, eine Liste von QComboBox, zu erstellen und die Verbindungen mit einem für machen, zum Beispiel:

QList <*QCombobox> l; 
l<<combobox1<< combobox2<< ....; 
for (auto combo: l) { 
    connect(combo, SIGNAL(activated(QString)), this, SLOT(fnEnable(QString)) 
}. 

Das gleiche mit QLineEdit getan würde.

+0

Das funktioniert! Das ist eine nette Art zu machen der Compiler erledigt die Arbeit am Grunt. Ich musste die 'for' Anweisung in' foreach (QComboBox * combo, 1) 'ändern (ich vergaß zu erwähnen, dass ich VC++ benutzte), aber es funktionierte wie ein Zauber. –

+0

Ich arbeite nicht vC++, aber vielleicht kannst du "for" aktivieren, indem du 'CONFIG + = C++ 14' zu deiner .pro-Datei hinzufügst – eyllanesc

+0

' foreach' tut genau dasselbe, aber ich muss nur den Typ für 'explizit erwähnen kombiniert. –

0

Sie können eine Initialisiererliste von Widgets Boxen und Hebel C iterieren ++ 11 für Sie alle die langweilige Arbeit zu tun:

MyClass::MyClass(QWidget * parent) : QWidget(parent) { 
    auto const comboBoxes = {Combo1, Combo2, ... }; 
    for (auto combo : comboBoxes) 
    connect(combo, &QComboBox::activates, this, &MyClass::fnEnable); 
} 

Sie können auch alle Kombinationsfelder automatisch finden:

MyClass::MyClass(QWidget * parent) : QWidget(parent) { 
    ui.setupUi(this); // or other setup code 
    for (auto combo : findChildren<QComboBox*>(this)) 
    connect(combo, &QComboBox::activated, this, &MyClass::fnEnable); 
} 

Oder Sie können automatisch an das Änderungssignal der Benutzereigenschaft anhängen. Dies funktioniert bei allen Steuerelementen mit der Benutzereigenschaft. Die Benutzereigenschaft ist die Eigenschaft eines Steuerelements, das die primären Daten enthält, die das Steuerelement anzeigt.

void for_layout_widgets(QLayout * layout, const std::function<void(QWidget*)> & fun, 
         const std::function<bool(QWidget*)> & pred = +[](QWidget*){ return true; }) 
{ 
    if (!layout) return; 
    for (int i = 0; i < layout->count(); ++i) { 
    auto item = layout->itemAt(i); 
    for_layout_widgets(item->layout(), fun, pred); 
    auto widget = item->widget(); 
    if (widget && pred(widget)) fun(widget); 
    } 
} 

class MyClass : public QWidget { 
    Q_OBJECT 
    Q_SLOT void MyClass::fnEnable(); // must take no arguments 
    ... 
}; 

MyClass::MyClass(QWidget * parent) : QWidget(parent) { 
    // setup code here 
    auto slot = metaObject()->method(metaObject()->indexOfMethod("fnEnable()")); 
    Q_ASSERT(slot.isValid()); 
    for_layout_widgets(layout(), [=](QWidget * widget){ 
    auto mo = widget->metaObject(); 
    auto user = mo->userProperty(); 
    if (!user.isValid()) return; 
    auto notify = user.notifySignal(); 
    if (!notify.isValid()) return; 
    connect(widget, notify, this, slot); 
    }); 
} 

Sie können die Kombinationsfelder auch in einem Array nach Wert beibehalten. Dies minimiert die Kosten der indirekten Verweisen und Ergebnisse in Code, der die geringste Menge an Speicher nehmen möglich und eine gute Leistung:

class MyClass : public QWidget { 
    Q_OBJECT 
    QVBoxLayout m_layout{this}; 
    std::array<QComboBox, 14> m_comboBoxes; 
    ... 
}; 

MyClass(QWidget * parent) : QWidget(parent) { 
    for (auto & combo : m_comboBoxes) { 
    m_layout.addWidget(&combo); 
    connect(&combo, &QComboBox::activates, this, &MyClass::fnEnable); 
    } 
} 
+0

Wenn es Ihnen nichts ausmacht zu fragen, wie unterscheidet sich die dritte Methode von der ersten? Werden Listen und Arrays anders behandelt? Oder ist es schneller, weil Sie keine vorhandenen Kombinationsfelder zu einer Liste hinzufügen, sondern bei der Initialisierung ein Array von Kombinationsfeldern erstellen? –

+1

Die dritte Methode unterscheidet sich, weil Sie die Kombinationsfelder in einem Array nach Wert halten. In der ersten Methode müssen Sie einen Container mit Zeigern für Kombinationsfelder erstellen. Du fragst mich nach Kaugummikugeln. Bei der ersten Methode gebe ich dir einen Stapel Post-its, jeder mit einer Stelle im Haus, wo ein Stück Kaugummi versteckt ist. Bei der zweiten Methode gebe ich dir eine Tube mit Kaugummikugeln. Es ist leicht zu sehen, welche Methode effizienter ist, um an die Kaugummikugeln zu kommen, und welche Methode am wenigsten fehleranfällig ist. –

Verwandte Themen