Vorschlag für die "Architektur" meines Widgets

Verschiedenes zu Qt
Antworten
bronko
Beiträge: 40
Registriert: 19. Mai 2009 15:49

Vorschlag für die "Architektur" meines Widgets

Beitrag von bronko »

Hallo zusammen,

ich möchte ein Widget erstellen, welches die Form einer Tabelle (QTableWidget) hat und Byte(HEX)-Werte darstellt. Jeder HEX-Wert soll bestimmte Attribute haben (z.B. verschiedene Hintergrundfarbe, Tooltip).
Die Daten (HEX-Werte u. Attribute) sollen über eine Methode übergeben/angehängt werden können.
In der Praxis möchte ich diese Klasse zum Betrachten von z.B. Echtzeitdaten des RS232 nutzen oder abspeichern und laden von Kommunikationssequenzen, ...
Es könne sehr viele Daten anfallen, z.B. 50MByte; Das ganze soll (auto)scrollbar sein und die Hintergrundfarben sollen dann für den sichtbaren Bereich geladen werden.
Ich besitze sehr gute C Kentnisse, einigermaßen C++ und QT nur in der Theorie bisher.

Meine Frage:
Wie soll ich das ganze aufziehen, damit ich mir für später nichts verbaue (z.B. eigener Thread, Bearbeitungsmöglichkeiten der Daten, ...). Ich habe von Model/View gelesen, kann dies aber leider (noch) nicht in die Praxis umsetzten (auf gut Deutsch: hab keinen Plan).

Für eine konkrete Antwort währe ich sehr Dankbar! Da ich denke dies könnte für andere nützlich sein, würde ich das später gerne hier posten.
Ich habe versucht den Code vonOkteta (KDE) zu lesen, leider bin ich noch zu unwissend.

Gruß
Bronko :(
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Eigentlich wäre meine Empfehlung dies mit Model/View umzusetzten, nur müsstest du für diesen Fall ein eigenes Model und eine eigene View schreiben.

Für den Anfang könntest du auch mal mit einem QTableView anfangen. Nichtsdestotrotz solltest du dich in das MVC-Thema mal einarbeiten. Es kann eine große Arbeitserleichterung mit sich bringen.
bronko
Beiträge: 40
Registriert: 19. Mai 2009 15:49

Beitrag von bronko »

Danke Upsala,
hab mal die letzten Tage etwas geschrieben und viel gelesen (MVC) leider nicht vollständig verstanden. Ich habe ein QAbstractListModel() für meinen seriellen Bytestrom abgeleitet und verwende nun eine abgeleitete Klasse von QTableView für die Darstellung.
Hier einige Fragen:
1. Ist es gut, daß ein Model ein Member von meiner abgleiteten View Klasse ist? Wenn ich nun einen neuen View für das gleiche Model schreibe,
sollen dann alle Views einen Zeiger auf ein globales Model nutzen?
Wie würden die Profis unter euch das machen? (Ich möchte meine Klassen später mit möglichst wenig Aufwand (kleine Interfaces) in verschiedene Projekte benutzen können)

2. Die reset() Methode des Models soll ein Neudarstellen aller Views erzwingen!? Macht sie auch. Wie schaffe ich es, das alle Spalten und Zeilen sofort die richtige Breite bzw. Höhe haben (mittels setRowHeight()). Momentan geht es nur, wenn ich die Spaltenanzahl der Tabelle über einen Slider ändere und dann reset() aufrufe:

Code: Alles auswählen

void CByteLoggerModel::setNumOfColumns(int columns)
{
	m_NumOfColumns = columns;
	/* update all views */
	reset();
}
Und das hier im Slot:
	this->setRowHeight(0,15);
	this->setRowHeight(1,15);


3. Jetzt möchte ich bei setzen eines Hackens erzwingen, dass unterhalb der jetzigen Tabelleneinträge Neue hinzukommen (gleiche Daten, nur halt als ASCII oder Dez dargestellt). Wie mach ich das? Müsste ich diese "neuen" Daten mir selbst generieren und dann in Abhängigkeit von dem Hacken, der Spaltenanzahl, usw. selbst in CByteLoggerModel::data() generieren und dann zurückgeben?

4. Spalten und -Zeilenbeschriftung (dynamisch, bei Änderung der Spaltenanzahl): Wie geht das? Hab mit setHorizontalHeader() experimentiert aber es nicht geschaft irgendetwas anderes als die Standard fortlaufende Nummer darzustellen :cry:

5. Hab mir eine tester Klasse gebastellt, die alle 100ms ein Byte generiert, welches über connect() an mein Model angehängt wird (das beherbergt die Daten). Ist das gut oder gibt es Verbesserungsvörschläge:

Code: Alles auswählen

void CByteLoggerModel::append(const QByteArray &a)
{
	m_byteData->append(a);
	// scroll zum Ende ?

	// erzwinge neu darstellen aller Views
	reset();
}
Ich komme leider echt nicht mehr weiter... :cry:
Dateianhänge
byteLoggerModel.h
(596 Bytes) 183-mal heruntergeladen
byteLoggerModel.cpp
(2.04 KiB) 195-mal heruntergeladen
byteLoggerView.cpp
(1.1 KiB) 191-mal heruntergeladen
bronko
Beiträge: 40
Registriert: 19. Mai 2009 15:49

Beitrag von bronko »

keiner eine Idee?
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

doch, aber sind recht viele voneinander abhängige Fragen mit langen Antworten :wink: .. ich versuche mich kurz zu fassen:
Ich habe ein QAbstractListModel() für meinen seriellen Bytestrom abgeleitet und verwende nun eine abgeleitete Klasse von QTableView für die Darstellung.
Ich sage nicht, dass dies nicht funktioniert, aber ich glaube, es gäbe schönere Lösungen. Was soll denn deine Tabelle können, was eine Qt-Tabelle nicht kann? Alle bisherigen Anforderungen (Farben, Tooltips, usw.) kannst du auch mit einem abgeleiteten "QAbstractTableModel" und einer fertigen "QTableView" erledigen..

1. Ist es gut, daß ein Model ein Member von meiner abgleiteten View Klasse ist?
Ja klar.. ein Model ist ein Member der View.. ("setModel()" bei QTableView)
Wenn ich nun einen neuen View für das gleiche Model schreibe,
sollen dann alle Views einen Zeiger auf ein globales Model nutzen?
Wenn alle Views die gleichen Daten anzeigen: ja. sonst: nein

2. Die reset() Methode des Models soll ein Neudarstellen aller Views erzwingen!? Macht sie auch. Wie schaffe ich es, das alle Spalten und Zeilen sofort die richtige Breite bzw. Höhe haben
ist evt. das: http://doc.trolltech.com/4.5/qtableview ... ToContents was du suchst?
3. Jetzt möchte ich bei setzen eines Hackens erzwingen, dass unterhalb der jetzigen Tabelleneinträge Neue hinzukommen (gleiche Daten, nur halt als ASCII oder Dez dargestellt). Wie mach ich das? Müsste ich diese "neuen" Daten mir selbst generieren und dann in Abhängigkeit von dem Hacken, der Spaltenanzahl, usw. selbst in CByteLoggerModel::data() generieren und dann zurückgeben?
Genau.. zuerst gibst du dem Model die "Freigabe" für was auch immer (z.B. neue Daten empfangen oder sonst was). Das Model generiert neue Zeilen und teilt der View mittels Signal mit, dass es neue Zeilen hat. Die View ruft die Zelleninhalte mittels data() ab.

Ich belasse es mal bei diesen Antworten, weil 4. davon abhängt, ob du nun eine saubere Lösung (mit TableView) nimmst oder beim TableWidget bleibst..

hth..
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Also,

ich habe momentan was in Arbeit, aber das wird noch ein paar Tage dauern (Screenshot)

Es gbt eine Ableitung vom QAbstractListModel vergleichbar mit dem QStringListModel und eine selbstgeschriebene View, da eine QTableView doch nicht ganz das Optimum für diese Darstellung ist.
Dateianhänge
hexview.png
hexview.png (55.33 KiB) 4375 mal betrachtet
bronko
Beiträge: 40
Registriert: 19. Mai 2009 15:49

Beitrag von bronko »

danke solarix, upsala,

@uspala: hattest du einen Screenshot dran? kann ihn nicht finden
Jetzt ist er da! Ja genau, aber warum hast du ein QAbstractListModel als Basis? Was ist der Unterschied für mich als QT Anfänger?
Ich sage nicht, dass dies nicht funktioniert, aber ich glaube, es gäbe schönere Lösungen. Was soll denn deine Tabelle können, was eine Qt-Tabelle nicht kann? Alle bisherigen Anforderungen (Farben, Tooltips, usw.) kannst du auch mit einem abgeleiteten "QAbstractTableModel" und einer fertigen "QTableView" erledigen..
Ich habe eine QTableView abgeleitet, weil ich denke so am flexibelsten zu bleiben. Außerdem kommte es mir auf ein sauberes Design an, so das ich in 1Jahr meinen eigenen Code noch (schnell) verstehe. Ich laß mich natärlich belehren: Kann ich denn mit einem "QAbstractTableModel" serielle Daten vernünftig handhaben (1-dimensional) was passiert wenn ich im nächsten Schritt die Daten in einer GraphicScene darstellen will, usw.
Zitat:
Wenn ich nun einen neuen View für das gleiche Model schreibe,
sollen dann alle Views einen Zeiger auf ein globales Model nutzen?

Wenn alle Views die gleichen Daten anzeigen: ja. sonst: nein
Hab mal versucht ein globales Model und ein View zu instanzieren und anschließend mittels setModel() zu verbinden. Das Programm stürzt unmittelbar vor Aufruf dieser Funktion ab. Wenn ich mit QT Creator/GDB/QT4.5.2 debugge läuft es sobald ich meinen Schieber für die Spaltenanzahl betätige. Vorher hatte ich meine View Klasse, welche einen private Zeiger auf mein Model hat (und im View Konstruktor erzeugt wurde). Das hat prächtig funktioniert.
Ziel ist jedoch das globale Model zu haben um die Daten mit vielen Unterschiedlichen Views zu verbinden. Die Bytes kommen vom Mikrocontroller und sollen z.B. als Bytestrom, Verteilung, Trend, ... dargstellt werden können.
Er kommt nie zu "4" mit meiner neuen Lösung:

Code: Alles auswählen

qDebug() << "1";
    m_loggerModel     = new CByteLoggerModel;
qDebug() << "2";
    m_loggerTableView = new CByteLoggerView;
qDebug() << "3";
    m_loggerTableView->setModel(m_loggerModel);
qDebug() << "4";
Zitat:

2. Die reset() Methode des Models soll ein Neudarstellen aller Views erzwingen!? Macht sie auch. Wie schaffe ich es, das alle Spalten und Zeilen sofort die richtige Breite bzw. Höhe haben

ist evt. das: http://doc.trolltech.com/4.5/qtableview ... ToContents was du suchst?
Eigentlich will ich etwas wie QTableView::setColumnWidth ( int column, int width ), leider funktioniert das nur, wenn ich ein Event fürs Neuzeichnen( Schieber betätigt) ausgelößt habe. Die Spalten UND Zeilen sollen einfach FIX von Anfang eine bestimmte größe haben.
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Hier eine funktionsfähige Demo zu obigen Screenshot.

Beim Model gibt es ein append, insert und remove.

Die View ist im Moment nur für die Darstellung gemacht, (getestet mit 1GByte QByteArray). Editierfunktionen lassen sich aber nachrüsten.
Dateianhänge
byteview.tar.gz
(5.29 KiB) 182-mal heruntergeladen
Antworten