Adatok hierachikus ábrázolására használjuk a TreeWidget és TreeView osztályokat. Mi a különbség köztük?
TreeView
- model vezérelt - setModel utasítással hozzárendelhetjük pl. egy sql query eredményét
- elemeit a model módosításával tudjuk manipulálni
- megjelenítésre szolgál
- szerkesztési lehetőségei szűkek
TreeWidget
- elem vezérelt - tőlünk függ a felépítése
- elemeit közvetlenül (model nélkül) manipulálhatjuk
- szerkeszteni tudjuk az elemeket
Ha mondjuk egy meghajtó könyvtár struktúráját ábrázoljuk, a TreeView a jó választás, hiszen itt sok mindent nem tudunk módosítani. De ha a fa elemeit módosítani szeretnénk, TreeWidget a megoldás. A programban a nagyobb alkotói szabadság jegyében a TreeWidget ( Tw )osztály használom. A Tw működését egymásra mutató pointerek biztosítják, hasonlóan a láncolt listákhoz. A pointerek formáját, kezelését a QTreeWidgetItem osztály biztosítja. Felépítését tekintve a "fa" törzsén vannak a vizsgálatok, az ágakon az automaták, és az ágak levelei lesznek az automata kódok.
A törzs részeit és az ágakat egy - egy QTreeWidgetItem típusú pointer alkotja. Fontos: egy pointert csak egyszer tudok a fára tenni
Nézzük a konkrét példát:
A programban egy vizsgálatot több automata is végezhet, ráadásul az automaták más - más kóddal küldik az eredményeket. Ezt kell egy editálható fa szerkezetben kell megvalósítani. Biztosítani kell a szerkesztés eseményeinek (elem kiválasztása kattintással, enter lenyomása, popup menü megjelenítése) kezelését is. Ezt a megszokott signal - slot párosításokkal oldjuk meg.
Funkciónként elmagyarázom a megoldásokat.
Vizsgálat hozzáadása
1. külön ablakban megadom a vizsgálat adatait, amiket adatbázisba írok.
2. sql query-vel visszaolvasom a vizsgálatok adatait
query.prepare("select vizsgalat_kodja, vizsgalat_id, vizsgalat_neve, mertekegyseg from vizsgalatok");
3. QStringList-be (oszlopok) beteszem a megjelenítendő adatokat
oszlopok << query.value(0).toString() << query.value(1).toString();
Az 1. rejtett oszlopban van a vizsgálat egyedi azonosítója
4. a query pörgetésével létrehozom az új elemeket, amiket a fa törzséhez illesztek (addTopLevelItem)
szulo = new QTreeWidgetItem(oszlopok);
szulo->setToolTip(0, query.value(2).toString());
widget.treeWidget->addTopLevelItem(szulo);
Elem kiválasztása
1. egy elemre kattintva megkapom a hozzátartozó pointert, és a tartalmát
itemClicked(QTreeWidgetItem * selItem, int selCol) signal hatására ide ugrik a vezérlés:
void RequestsForm::elem_kivalasztasa_slot(QTreeWidgetItem * selItem, int selCol)
A selCol tartalmazza a cella sorszámát. Itt a 0. a vizsgálat neve és az automaták neve is
Mivel a vizsgálatok és az automaták neve is a 0. oszlopban van, mi dönti el, hogy melyikre kattintottam? Ez: selItem->parent(). Ha nulla a visszakapott érték, vizsgálatra - szülőre - kattintottam. Ha nem nulla, akkor automatára - gyerekre -.
Vizsgálat módosítása
Az elem kiválasztása után újra felhasználom a vizsgálat hozzáadásakor használt ablakot
modosit_groupBox = widget.uj_vizsg_groupBox;
modosit_groupBox->setTitle(trUtf8("Vizsgálat adatainak módosítása"));
Ezzel a megoldással az új vizsgálatkor használt ellenőrzéseket újrahasznosítom. Ha átmentek az adatok az ellenőrzésen -> sql update. Itt jön be az 1. -rejtett- oszlop:
vizsgalat_id = kivalasztott->text(1);
Automata hozzáadása
1. ComboBox-ot feltöltök a megjelenítendő adatokkal
2. A megfelelő oszlopba beillesztem a comboBox-ot (setItemWidget)
void RequestsForm::automata_hozzaadasa() {
if (kivalasztott->parent() != 0) {
return;
}
widget.automatak_comboBox->setVisible(true);
kivalasztott_automata = new QTreeWidgetItem(kivalasztott);
kivalasztott_automata->setText(0, "automata");
widget.treeWidget->setCurrentItem(kivalasztott_automata);
widget.treeWidget->setItemWidget(kivalasztott_automata, 0, widget.automatak_comboBox);
}
a. ha a kiválasztott elemnek va szülője (parent () != 0), akkor egy automatára kattintottam, ahhoz pedig nem adunk újabb gyereket
b. elem létrehozása, mint a vizsgálat hozzáadásánál, de itt a szülő a "kivalasztott" lesz, az a vizsgálat, amelyikhez automatát akarok hozzáadni
c. a már aktuális elem (automata) 0. oszlopában megjelenítem az automaták nevével feltöltött comboBox-ot
3. a comboBox egy elemének kiválasztását signal - slot kapcsolattal kezelem le, majd a még szükséges adatokat az előbb vázoltak szerint bekérem
widget.treeWidget->setItemWidget(kivalasztott_automata, 2, widget.kod_be_lineEdit);
Automata módosítása
Hasonlóan működik a vizsgálat kiválasztásához, csak itt van a kiválasztott elemnek szülője
Összefoglalva
- Már létező elemeket kezelni a QtreeWidgetItem osztályon keresztül
- elemet a törzshöz adni a TreeWidget::addTopLevelItem(s) segítségével
- elem kiválasztását lekezelni TreeWidget::itemClicked(QTreeWidgetItem * selItem, int selCol) signal-al
- elemhez widget-et (comboBox, lineEdit, stb.) rendelni setItemWidget(QTreeWidgetItem * item, int column, QWidget * widget). A widget-nek setVisible() = true- nak kell lennie a hozzárendelés előtt
- gyereket a törzs egy eleméhez adni a gyerek = new QTreeWidgetItem(QTreeWidgetItem *szulo) formában
tudunk.