[gelöst] QTableView ineffizient

Alles rund um die Programmierung mit Qt
lespaul
Beiträge: 87
Registriert: 11. August 2011 10:07

[gelöst] QTableView ineffizient

Beitrag von lespaul »

Hallo Leute,

ich habe eine Binäre Datei --> ca. 1-2 Megabytes, diese hat viele Datensätze (Datum+Messwerte).

Ein Datensatz sind immer 32 Bytes ( := 8 Bytes (Datum+Uhrzeit) + 24 * Byte einzelne Messwerte), also zB:
00 00 00 00 C0 E4 D3 40 02 07 0A 11 12 29 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FE
Byte 0-7 = Datum (00 00 00 00 C0 E4 D3 40)
Byte 8-31 einzelne Byte-Messwerte (02 07 0A 11 12 29 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FE)

Ich möchte die Messwerte in einer Tabelle ausgeben, ein Datensatz entspricht eine Zeile. Beispiel oben etwa:
| Datum | 1. Wert | 2.Wert | 3.Wert | ... | 23.Wert | 24.Wert |
...
| 24.11.2013 | 2 | 7 | 10 | 17 | 41 | 255 | ... | 0 | 254 |
...

Bis jetzt habe ich eine QTableWidget, in diese füge ich alle einzelnen Felder einzeln hinzu (mittels 2fach verschachtelter for-Schleife). Das kommt mir sehr ineffizient vor.. Wäre es mit einem Model/View effizienter?

Thnx und mfg Lespaul
Zuletzt geändert von lespaul am 4. Februar 2014 08:24, insgesamt 1-mal geändert.
sigvdr
Beiträge: 100
Registriert: 1. Juli 2008 19:29

Re: QTableView ineffizient

Beitrag von sigvdr »

Aber sicher doch!

Mit QTableWidget musst du den gesamten Datenbestand in die "Tabellenstruktur" hineinkopieren und damit viele viele QTableWidgetItems anlegen.
QTableView fordert von seinem Model immer nur die gerade benötigten sichtbaren Daten.
Anmerkung: Im Model müssen die Daten auch nicht in einer "Tabellenstruktur" vorhanden sein.
Beispiel: http://www.qtforum.de/forum/viewtopic.p ... 168#p77179
Gruß Sig
lespaul
Beiträge: 87
Registriert: 11. August 2011 10:07

Re: QTableView ineffizient

Beitrag von lespaul »

Vielen Dank für die Antwort. Ich bin dabei mein Projekt auf das Model/View Konzept umzustellen. Dazu hätte ich eine Frage:

1.)
Ein Datensatz ist ja folgendermaßen (Datum Wert1 Wert2 ... Wert24). Ich übernehme das Beispiel bei qt-project, dort wurden jede Zeile in eine QList<QVariant> gepackt. Bei mir foglen für einen Datensatz nach dem Datum 24 unsigned char Werte (0-255). Diese 8bittigen Werte als QVariant und dann bei 10000 Datensätzen .. hmmm ich weiss ehrlich gesagt grad nicht, wie ein QVariant auf dem Arbeitsspeicher aussieht? Hängt vermutlich vom Inhalt ab?

Code: Alles auswählen

//..
QVariant(QChar c)
QVariant(const QDate & val)
//..
Wenn ich eine char (8bit) reinpacken würde, würde diese dort dann auch 8bit abgespeichert?
Würdet ihr eine eigene Datenstruktur für einen Datensatz schreiben a la

Code: Alles auswählen

class EinDatensatz
{
 //...
private:
    QDate ds_datum;
    quint8[24] ds_werte; 
}
?

Macht es Sinn, dann später

Code: Alles auswählen

QList<EinDatensatz> myModel;
mit wohlmöglich über 10000 Zeilen zu verwenden?? Bin grad verwirrt..
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Re: QTableView ineffizient

Beitrag von RHBaum »

Dein Problem ist, das Du "im ganzen" denkst ....
Das heisst du willst alle infos bevor du das Model befüllst.

Und genau das ist der Vorteil des Model View Konzepts's, daß du genau das nicht brauchst.
Eigentlich spricht man von MVC - Model View Conntroller .... nur hier ist model + View gleichzeitig der Controller
vereinfacht erklärt: Das View fragt das Model, was zu zeigen ist. Dann zeigt das View nur einen Bestimmten bereich der Gesamten Daten an, wenn die daten so gross sind, das sie nicht aufs mal dargestellt werden.
Dafür informiert das Model den view, wenn sich was geändert hat. Das View entscheidet dann, ob was zu tun ist, und fragt die relevanten daten bei Bedarf neu ab ...

ALso das einzige was das Model im "Vorfeld" wissen muss und relativ haeufig abgefragt wird, ist die Struktur, und die Dimension (Zeilen / Spalten anzahl) .... und das auch nicht immer, models können auch "wachsen"
Alles andere fragt das ding "bei Bedarf".

WIllst du ein performantes Model auf Dateibasis, wirst du die datei nicht komplett auslesen.
du wirst deinem model einfach das datei-Handle geben ....
Die struktur gibst du selber vor. Ich nehm an es wird was mit fixen Spalten und variablen Zeilen.

Du hasst ne fixe Dateistruktur ohne variablen Anteil (aka Strings mit variabler Länge)?
Dann ists recht einfach ... Die Anzahl der Zeilen bekommst dann aus der dateigroesse.
die Abfrage bestimmter elemente (index) bekommst ueber die File Posi - einfach zeiger positionieren - auslesen - in Rueckgabe verpacken. Vielleicht bissi cachen für die Performance

Hasst du variable anteile, musst du einmal komplett scannen und Ne index liste erstellen ... also sowas wie: Datensatz 1264 beginnt an file Posi 129047 ....
Damit kennst dann auch die Zeilenzahl .... und zugriff geht dann halt nur ueber die Zwischenliste.
Wird diese Zwischenliste zu groß, kannst die auch in ner Temp Datei "auslagern" .....
Mit Multithreading KnowHow kannst das Model dann auch so bauen, das alle funktionen aus dem GUI Thread flott zurueck kehren, Aka das View sofort angezeigt wird, und das Model parralel aufgebaut wird, aka mit der Zeit befüllt ...

Und schon brauchst dir keinen kopf machen, wie gross deine Dateien sind und was alles in den Arbeitsspeicher passt .....
und alle finden toll das dein View sofort was anzeigt und nicht erst mal zig min daten einliest und umherswappt ^^

Ciao ...
lespaul
Beiträge: 87
Registriert: 11. August 2011 10:07

Re: QTableView ineffizient

Beitrag von lespaul »

Vielen Dank für deine Antwort!
RHBaum hat geschrieben:WIllst du ein performantes Model auf Dateibasis, wirst du die datei nicht komplett auslesen.
du wirst deinem model einfach das datei-Handle geben ....
Das hört sich super an, ich wollte auch auf sowas hinaus..
RHBaum hat geschrieben:Die struktur gibst du selber vor. Ich nehm an es wird was mit fixen Spalten und variablen Zeilen. Du hasst ne fixe Dateistruktur ohne variablen Anteil (aka Strings mit variabler Länge)?
Dann ists recht einfach ... Die Anzahl der Zeilen bekommst dann aus der dateigroesse.
Richtig! Beispielsweise :

Code: Alles auswählen

QByteArray myPayload(filehandler.readAll());

long filesize = myPayload.size(); // Dateigröße Bsp. 230400 bytes
int ds_size = 32; // pro Datensatz
long ds_count = filesize / ds_size; // ergäbe 7200 Zeilen an Datensätzen

// alle Datensätze der Reihe nach auslesen
for (long i = 0; i < ds_count; i++)
{
   QByteArray ein_ds = myPayload.mid(i*32, 32);
}
RHBaum hat geschrieben: die Abfrage bestimmter elemente (index) bekommst ueber die File Posi - einfach zeiger positionieren - auslesen - in Rueckgabe verpacken. Vielleicht bissi cachen für die Performance
Das ist doch das was du meinst, und genau das was ich brauche http://doc.qt.digia.com/qq/qq15-models. ... tfilemodel ? Ich werd mich gleich heut abend dran setzten und freu mich schon :D
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Re: QTableView ineffizient

Beitrag von RHBaum »

ist die dynamische Variante .... weil keine binaere fixe datenstruktur.
Die muessen auf die Lineendings parsen und sich die Posi liste halten ... (mutable QVector<int> offsets;)
das alles brauchst du gar ned ...

in der data(const QModelIndex & index, int role) methode kannst dir die FilePosi einfach ala
index.row() * DATASIZE berechnen und da die daten auslesen ...

dein model wär viel einfacher als das da besprochene ...

Nur als Tipp:
Byte 0-7 = Datum (00 00 00 00 C0 E4 D3 40)
Byte 8-31 einzelne Byte-Messwerte (02 07 0A 11 12 29 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FE)

Code: Alles auswählen

struct DataEntryT
{
    quint64 timestamp;
    quint8   data[24];
};
dank 8 ByteAllignment bietet sich sowas als Type förmlich an :-)

Ciao ...
lespaul
Beiträge: 87
Registriert: 11. August 2011 10:07

Re: QTableView ineffizient

Beitrag von lespaul »

Supi, funzt sowit prima.

Hab nur noch ne kleine Frage zu den Widgets:
QMainWindow -> QWidget -> QVBoxLayout -> QTabWidget -> QWidget -> QVBoxLayout -> ..
|
Wenn ich das Hauptfenster maximiere, bleibt das QTabWidget unskaliert.. Jemand eine Idee?
sigvdr
Beiträge: 100
Registriert: 1. Juli 2008 19:29

Re: QTableView ineffizient

Beitrag von sigvdr »

Das TabWidget durch maximumSize() begrenzt, oder QSizePolicy::fixed.
Gruß Sig
lespaul
Beiträge: 87
Registriert: 11. August 2011 10:07

Re: QTableView ineffizient

Beitrag von lespaul »

sigvdr hat geschrieben:Das TabWidget durch maximumSize() begrenzt, oder QSizePolicy::fixed
Auch wenn ich Expanging einstelle, bleibt es so unglkücklich.

Desweiteren sind auch der Inhlat meiner Tabellenfelder linksbündig. Gegoogelt könnte ich die Alginment einstellen a la:

Code: Alles auswählen

QVariant MeinModel::data ( const QModelIndex & index, int role ) const
{
if (role == Qt::TextAlignmentRole)
return Qt::AlignCenter;
//..
}

Pustekuchen, will bei mir nicht.. :(
sigvdr
Beiträge: 100
Registriert: 1. Juli 2008 19:29

Re: QTableView ineffizient

Beitrag von sigvdr »

Code: Alles auswählen

QVariant MeinModel::data ( const QModelIndex & index, int role ) const
{
if (role == Qt::TextAlignmentRole)
return Qt::AlignCenter;
//..
}
Richtig! Exakt genau so muss das gehen.

Gruß Sig
lespaul
Beiträge: 87
Registriert: 11. August 2011 10:07

Re: QTableView ineffizient

Beitrag von lespaul »

sigvdr hat geschrieben:Richtig! Exakt genau so muss das gehen.
Weder

Code: Alles auswählen

return Qt::AlignCenter;
noch

Code: Alles auswählen

return Qt::AlignHCenter;
machen den Inhalt meiner Tabelle mittig. Die Spaltenüberschirften sind mittig, mir geht es aber mehr um den eigentlichen Tabelleninhalt..
sigvdr
Beiträge: 100
Registriert: 1. Juli 2008 19:29

Re: QTableView ineffizient

Beitrag von sigvdr »

Wie schon gesagt, genau so muss es gehen. Falls das bei dir nicht so ist, dann liegt das an einem anderen Fehler, den es zu finden gilt.
Zeig uns mal den Code von data(...) komplett.

Gruß sig
lespaul
Beiträge: 87
Registriert: 11. August 2011 10:07

Re: QTableView ineffizient

Beitrag von lespaul »

Code: Alles auswählen

QVariant MeasureTableModel::data(const QModelIndex &index, int role) const
{
    // Grenzen sprengen
    if (!index.isValid()
            || index.row() > record_count
            || index.row() < 0 || role != Qt::DisplayRole)
        return QVariant();

    if (role == Qt::TextAlignmentRole) return Qt::AlignHCenter;

    // Open File
    if (!importFile->open(QIODevice::ReadOnly)) return QVariant();

    importFile->seek( index.row()*RECORD_SIZE );
    QByteArray bytes = importFile->read(RECORD_SIZE);
    importFile->close();

    if (bytes.size() != RECORD_SIZE) return QVariant();

    return QVariant(MeasureValues::getSetAsVariant(bytes).at(index.column()));
}
MichaelS
Beiträge: 240
Registriert: 27. Dezember 2005 12:49

Re: QTableView ineffizient

Beitrag von MichaelS »

Code: Alles auswählen

|| role != Qt::DisplayRole)
        return QVariant();
Aufgrund dieser Anweisung kommt Dein Programm gar nicht mehr zur Formatierung.

Gruß Michael
lespaul
Beiträge: 87
Registriert: 11. August 2011 10:07

Re: QTableView ineffizient

Beitrag von lespaul »

Auskommentiert oder gelöscht

Code: Alles auswählen

/*|| role != Qt::DisplayRole*/ )
Habe ich nun lauter Checkboxen in jedem Feld in der Tabelle? :?:
Antworten