Seite 1 von 1

QComboBox mit eigener Klasse füllen.

Verfasst: 8. Oktober 2010 13:27
von skeemo
Hallo zusammen,

ich bin neu in QT, kenne mich aber recht gut mit andern Frameworks wie z.B. Flex oder .NET aus.

Zum "üben" habe ich ein 08/15 Widget gebaut das folgendes tut / tun soll :

- eine Combobox
- ein Button zum Hinzufügen eines Datensatzes (dazu gleich mehr)
- ein Label zum Anzeigen des in der Combobox ausgewählten Datensatzes.

Ein Datensatz besteht aus der total kreativen eigenen Klasse "Person" die über die Eigenschaften "Vorname", "Nachname" und "Alter" verfügt.

Ich zeige auf Buttondruck einen Dialog in dem ich eine neue Person anlege und übergebe die mittles eines Signals an das Widget.
Soweit so gut.
Was ich nun möchte ist, die ComboBox mit den Nachnamen (z.B.) zu füllen und bei Auswahl eines Eintrags ALLE Daten der entsprechenden Person im Label anzuzeigen.
Anscheinend kann ich aber die Einträge der Combobox NICHT direkt mit den Objekten der Klasse Person verknüpfen sondern nur mit einzelnen Strings.
Also führe ich eine QList<Person> in der die wirklichen Objekte stehen und kann mit den ComboBox - Indizes die richtigen String-Objekt Beziehungen herstellen.

Was mir nun gar nicht gefällt, ist allerdings die Tatsache, dass wenn ich die ComboBox alphabetisch sortiere (was ja per Flag möglich ist), ich die andere Liste manuell nachsortieren muss. Also bei jedem Hinzufügen.

Das finde ich sehr umständlich und unflexibel, und ich frage mich warum es keine komfortablere CollectionKlasse gibt, bzw. warum ich nicht direkt Daten an die ComboBox binden kann.

Darüberhinaus...natürlich habe ich versucht die QList manuell zu sortieren mit qSort und einer eigenen LessThan Funktion. Da habe ich mich aber irgendwie zu blöd angestellt.

Für Ideen, Hinweise, Tips wäre ich sehr dankbar.

Gruß

Chris.

Verfasst: 8. Oktober 2010 13:49
von pfid
http://doc.trolltech.com/4.6/qcombobox.html#setItemData

Damit kannst du der Combobox, für den gegebenen Index, Extradaten übergeben. Dabei wird ein QVariant gespeichert, du kannst hier also auch einen Pointer auf dein Person-Objekt speichern (wie man einen Pointer in QVariant speichert -> google selbiges, 1. oder 2. Treffer dürfte eine gute Anleitung bereit halten).

Verfasst: 8. Oktober 2010 14:02
von skeemo
Hm das ist ne gute Idee.
QVariant habe ich schon im Zusammenhang mit der Combobox gesehen. Das kann man auch direkt beim Eintrag-adden mitgeben, eider konnte ich (natürlich) nicht direkt meinen eigenen Datentyp anhängen.

Ich werds dann mal so wie hier versuchen:
http://www.pronix.de/comment/site-963/o ... ite-1.html

ps. Das finde ich aber schon insgesamt etwas umständlich.


Danke für die Hilfe.

Weitere Vorschläge sind natürlich immer noch willkommen ;)[/url]

Verfasst: 8. Oktober 2010 14:40
von solarix
Pointer zu qulonglong? Wie bekloppt ist das denn..

Ich würde den in der Doku vorgeschlagenen Weg bevorzugen:

Code: Alles auswählen

MyClass *i = ...
QVariant v = qVariantFromValue<void*>(i);

...
MyClass *i2 =  (MyClass*)qVariantValue<void*>(v); // allenfalls noch mit hübscherem cast (static)

hth..

Verfasst: 8. Oktober 2010 15:53
von padreigh
Wie speicherst du die Datensätze? QList<Person> ?
Dann pack doch einfach die Position in der QList per setItemData(comboboxindex, QVariant(personenlistenposition), Qt::UserRole ) mit in die Combobox .... solange du nicht in der Liste rumsortierst kannst du mit der Combobox machen was du willst ... willst du den passenden Datensatz wissen reicht ein einfaches personenliste.at(QComboBox::itemData ( currentIndexDerComboBox, Qt::UserRole ).toInt()) . Nix rumpointern. Wenn du die Reihenfolge der Liste änderst, musst du die Combobox neu füllen ... aber solange du nicht den Datencontainer durcheinanderbringst sollte das tun ...

Code: Alles auswählen

QComboBox.clear(); 
for(int i=0;i<personenliste.size();++i) 
{ 
  QComboBox.insert(i,personenliste.at(i).name(),QVariant(i));
}
um sie neu zu füllen...

Verfasst: 8. Oktober 2010 15:59
von pfid
Mit rumpointern ist die Zeile in der Box aber direkt einem Objekt zugeordnet, und unabhängig von allen anderen Listen, Indices etc. .

Verfasst: 8. Oktober 2010 17:34
von skeemo
..und genau das ist mein Gedanke. Ich will nicht, dass einfach lose Strings in der Combobox Liste stehen, sondern sich jeder Eintrag direkt einem Objekt zuordnen lässt.

Ich bin halt die komfortablen Data-Bindings aus Flex gewohnt. Mir ist schon klar, dass dort im Grunde auch nichts gross anderes unter der Oberfläche passiert...

@Solarix

Danke das werde ich mal probieren...


ps. Schön, mal in einem Forum auch wirklich Hilfe zu bekommen :)

Verfasst: 8. Oktober 2010 17:53
von skeemo
So es funktioniert jetzt :)

Falls jemand den Code sehen möchte:

Code: Alles auswählen

// Slot
void MainWindow::createdPerson(Person *p)
{
    QVariant variant = qVariantFromValue<void*>(p);
    personList->addItem(p->nachname(),variant);
    createDlg->clean();
    createDlg->close();
}
.
.
.
// Slot von der Combobox
void MainWindow::personSelected(int index)
{    
    QVariant variant = personList->itemData(index);
    Person *selectedPerson = (Person*)qVariantValue<void*>(variant);
    
    //...Daten anzeigen usw. 
   
}


Verfasst: 8. Oktober 2010 17:53
von Christian81
Die Lösung von padreigh ist der normale Weg abgesehen von der Tatsache dass die Infos aus einer DB kommen und demnach über eine eindeutige ID anstatt die Listen-Index bestimmt werden.