Hogyan tudjuk megjeleníteni az adatbázisban tárolt adatainkat? Táblázatban vagy mezőnként. Mindkét megoldásra mutatok példát, kezdjük a táblázattal.
A TableView egy model adatait mutatja meg táblázatos formában.
Ehhez először meg kell határozni a modelt:
QSqlQueryModel *model = new QSqlQueryModel;
model->setQuery("select...");
Ha az ablak megjelenésével együtt mutatjuk meg az adatokat, akkor javasolt a konstruktorba tenni. A "select" utasításban határozzuk meg, hogy mi jelenjen meg. De mivel alapban a select-ben megadott mezőneveket teszi be a progi a header-be, ezt illik emberi formára módosítani:
model->setHeaderData(0, Qt::Horizontal, trUtf8("ID"));
model->setHeaderData(1, Qt::Horizontal, trUtf8("Megnevezés"));
model->setHeaderData(2, Qt::Horizontal, trUtf8("Indító pr."));
model->setHeaderData(3, Qt::Horizontal, trUtf8("Aktív"));
model->setHeaderData(4, Qt::Horizontal, trUtf8("Kapcs. típ."));
A trUtf8 biztosítja az ékezetes karakterek helyes megjelenítését. A TableView fejlécét a "QHeaderView" osztály segítségével módosítom. Először megcsinálom az összerendelést.
hv = new QHeaderView(Qt::Horizontal);
widget.tableView->setHorizontalHeader(hv);
A mezők szélességét is be kell állítani:
hv->setDefaultSectionSize(60);
hv->resizeSection(0, 30);
hv->resizeSection(1, 210);
hv->resizeSection(2, 210);
for (int i = 5; i < hv->count(); i++) {
hv->hideSection(i); }
Nem fogom egyenként állítgatni őket, hanem veszek egy alapot (60) és az ettől különbözőket módosítom. A "for" ciklusban a select-ben szereplő többi mezőt elrejtem. A section-t azonosító logikai index 0-val kezdődik. A táblázat adatait rendezni is kellhet különböző mezőkre, az erre szolgáló bigyót piros körrel jelöltem.
hv->setSortIndicatorShown(true);
hv->setClickable(true);
if (irany == "asc") {
hv->setSortIndicator(1, Qt::AscendingOrder);
} else {
hv->setSortIndicator(1, Qt::DescendingOrder);
}
A második sorban állítom be, hogy generálódjon clicked üzenet a fejlécre kattintásnál. A clicked üzenethez hozzárendelek egy függvényt.
connect(hv, SIGNAL(sectionClicked(int)), this, SLOT(rendezes_slot(int)));
Az üzenet hatására a függvényre ugrik a vezérlés.
void AutomataForm::rendezes_slot(int oszlop) {
if (oszlop != 1) {
hv->setSortIndicatorShown(false);
return;
}
hv->setSortIndicatorShown(true);
if (hv->sortIndicatorOrder() == Qt::AscendingOrder) {
adatok_beolvasasa("asc");
} else {
adatok_beolvasasa("desc");
}
}
Az "oszlop" változó tartalmazza a kiválasztott mező index-ét. Nálunk a megnevezés mező a szerencsés kiválasztott, így csak akkor rendezem le az adatokat, ha arra kattint a felh. A többi fejlécre kattintásnál letiltom a rendezés jelet. Az "adatok_beolvasasa" függ. paramétere a rendezés iránya, amit egyszerűen hozzámásolok a "select" utasításhoz:
void AutomataForm::adatok_beolvasasa(QString irany) {
model->setQuery("select... order by megnevezes " + irany, db_leiro);
Mi van, ha mondjuk módosításnál az automata azonosítójára van szükségem, de bármelyik cellára kattinthat a felh.? Erre van a TableView clicked signal, amit a Qt Designer-ben rendeltem egy függvényhez.
connect(widget.tableView, SIGNAL(clicked(QModelIndex)), this,SLOT(automata_kivalasztasa_slot(QModelIndex)));
És a függvény:
void AutomataForm::automata_kivalasztasa_slot(QModelIndex selItem) {
automata_id = selItem.sibling(selItem.row(), 0).data().toString();
A kiválasztott cellához tartozó sor 0-s sorszámú (legelső) mezőjénak tartalmát veszem ki.
Mezőkénti adatmegjelenítésre pl. akkor van szükség, ha adatokat akarok módosítani. Tudom, erre van lehetőség a TableView vagy TableWidget osztályoknál is, de szerintem szebb, ha külön mutatom meg a módosítható adatokat. Ehhez a Qt Designer-ben felpakolom a szükséges adatbeviteli mezőket (linedit, combobox, spinbox, stb). Az előbbiekhez hasonlóan kiveszem az adatokat a táblázatból, és értékadással feltöltöm őket.
widget.megnevezes->setText(selItem.sibling(selItem.row(), 1).data().toString());
widget.indito_pr_neve->setText(selItem.sibling(selItem.row(), 2).data().toString());
widget.aktiv_comboBox->setCurrentIndex(selItem.sibling(selItem.row(), 13).data().toInt() - 1);
widget.soros_tcp_comboBox->setCurrentIndex(selItem.sibling(selItem.row(), 14).data().toInt());
Ugye az elején láttuk, hogy csak az első öt mezőt jelenítem meg a "select" által visszaadott adatokból. A többi adat is rendelkezére áll, még ha nem is látható. Így a 13,14 a "select" vonatkozó mezőinek sorszámát jelenti.
Az előző bejegyzés végén írtam, hogy a felhasználói adatbevitel a legveszélyesebb része a program futásának, így minél jobban korlátozni kell ezt a műveletet. Íme két példa:
Soros adatátvitelnél tudnom kell az adatbitek számát. Ez 4 - 8 érték lehet. Ha hagyom, hogy a user egy lineedit mezőbe írja be az értéket, tízből tízszer el fogja rontani, ráadásul még ellenőriznem is kell a bevitt adatot. Ezt kikerülve egy spinbox-ot használok, beállított értékekkel
Ha nem tudom teljesen lekorlátozni az adatbevitelt, akkor is igyekszem szűkíteni a hibalehetőségeket.
Itt pl. maszkolom az adatbevitelt, vagyis csak számokat vihet be. Megadok egy default értéket is, ha ettől különböző értéket kapok a vizsgálatnál, akkor valszeg jó adatot írt be.