[gelöst] Darstellung von Daten aus einer SQL-Datenbank

Alles rund um die Programmierung mit Qt
Antworten
Luftballon
Beiträge: 29
Registriert: 10. Mai 2009 20:03

[gelöst] Darstellung von Daten aus einer SQL-Datenbank

Beitrag von Luftballon »

Hallo zusammen!

Ich habe gerade ein Programm geschrieben, dass Daten (MultipleChoice-Fragen) aus einer SQL-Datenbank ausließt und diese in QTextEdit schreibt.

Jetzt möchte ich die allerdings ansprechender darstellen. Und zwar in etwa so wie in dem angehängten Bild.

In der Vergangenheit habe ich viel mit HTML/PHP5/MySQL gemacht. Dort habe ich ein HTML-Template verwendet, in das PHP5 die Daten aus der MySQL-Datenbank gesetzt hat. Dieses geschah in einer Schleife, wo dies repetitiv stattfand.

=====================
Eine erste Idee von mir wäre daher:
1)
Als Template eine Klasse die von QWidget abgeleitet erstellen, die die Daten aus der Datenbank darstellt

2)
Diese Klasse wird in der folgenden Schleife für jede Frage instanziert

Code: Alles auswählen

QSqlQuery query;
	query.exec("SELECT * FROM question");
	QSqlRecord record = query.record();
	while( query.next() ) {
		myWidget = new MyWidget(query.value());
		vBoxLayout->addWidget(myWidget);
	}
3)
Die Klasse kümmert sich dann um die Darstellung
=====================

Könnte das so in etwa funktionieren? Wenn ja, dann müsste ich aber wohl ein Array (in C++ heißt das glaube ich Feld) für myWidget benutzen und das mit der Übergabe der Daten aus der Datenbank funktioniert so wohl auch nicht. ;-)

Oder wie macht ihr sowas?

Ich würde mich sehr über eure Hilfe und Tipps freuen!

Beste Grüße,
der Luftballon
Dateianhänge
Bildschirmfoto.png
Bildschirmfoto.png (23.47 KiB) 6622 mal betrachtet
Zuletzt geändert von Luftballon am 21. Mai 2009 13:50, insgesamt 1-mal geändert.
Luftballon
Beiträge: 29
Registriert: 10. Mai 2009 20:03

Beitrag von Luftballon »

Moin Moin!

Ich brüte noch über dem Problem bezüglich der Darstellung der MC-Fragen aus der Datenbank. Die Darstellung funktioniert mit dem Code (siehe unten). Allerdings finde ich die Lösung nicht besonders elegant. Aktuell schreibe ich jeden Wert eines Datenbankfeldes in ein QString und übergebe diesen bei der Instanzierung an die Template-Klasse. Das scheint mir sehr umständlich und wird auch bei steigender Anzahl von Feldern unübersichtlich.

Ich würde gerne nur einen "Variablen-Container" übergeben, in dem alle Daten einer Frage sind. Allerdings werden später nicht alle Felder vom Typ QString sein.

Wie könnte ich das gescheiter lösen?

mainwindow.cpp

Code: Alles auswählen

[...]
QSqlQuery query;
query.exec("SELECT * FROM question");
int n = query.size();
int i = 0;
TplQuestion *tpl[n];
QSqlRecord record = query.record();
		
while( query.next() ) {
	QString q 	= query.value(record.indexOf("question")).toString();
	QString a_1 = query.value(record.indexOf("answer_1")).toString();
	QString a_2 = query.value(record.indexOf("answer_2")).toString();
	QString a_3 = query.value(record.indexOf("answer_3")).toString();
	QString a_4 = query.value(record.indexOf("answer_4")).toString();
	QString a_5 = query.value(record.indexOf("answer_5")).toString();
	tpl[i] = new TplQuestion(q, a_1, a_2, a_3, a_4, a_5);
	VBox->addWidget(tpl[i]);
	i++;
}
[...]
tplQuestion.cpp

Code: Alles auswählen

#include "tplQuestion.h"

TplQuestion::TplQuestion(QString q, QString a_1, QString a_2, QString a_3, QString a_4, QString a_5) {
	question = new QLabel(q);
	answer_1 = new QLabel(a_1);
	answer_2 = new QLabel(a_2);
	answer_3 = new QLabel(a_3);
	answer_4 = new QLabel(a_4);
	answer_5 = new QLabel(a_5);
	
	layout = new QGridLayout(this);
	layout->addWidget(question, 1, 0);
	layout->addWidget(answer_1, 2, 0);
	layout->addWidget(answer_2, 3, 0);
	layout->addWidget(answer_3, 4, 0);
	layout->addWidget(answer_4, 5, 0);
	layout->addWidget(answer_5, 6, 0);
}
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Wie wäre es alternativ mit folgendem Konstruktor:

Code: Alles auswählen

TplQuestion::TplQuestion( const QString& question, const QVariantList& answers )
 : m_question(question), m_answers(answers)
{...}
Dann hast du variable Länge der Antworten und Option, auch andere Typen als QString in den Antworten zu hinterlegen.
Luftballon
Beiträge: 29
Registriert: 10. Mai 2009 20:03

Beitrag von Luftballon »

In den Qt's Classes (http://doc.trolltech.com/4.5/classes.html) kann ich QVariantList nicht finden. Und was ist die Funktion diesen Angangs ": m_question(question), m_answers(answers)" ?

Die Anzahl der Antwortmöglichkeiten wird sich nicht ändern. Aber es kommen noch weitere Informationen dazu wie z.B. richtige Antwort, Autor, Kategorie usw.

Mit PHP kann man alle Felder eines Datensatzes in ein Array schreiben und dann dieses Array einer Funktion übergeben. Das würde beispielsweise so aussehen:

Code: Alles auswählen

/*
Struktur von $row:
  $row['question'] = "Welche Farbe hat ein Apfel?";
  $row['antwort_1'] = "blau";
  $row['antwort_2'] = "rot";
  $row['antwort_3'] = "grün";
  $row['antwort_4'] = "gelb";
  $row['antwort_5'] = "schwarz";
  $row['richtig'] = 2;
  $row['kategorie_id'] = 32;
*/
while ($row = mysql_fetch_array($result)) {
   $object = new MyClass($row);
   $object->show();  
}
Eine vergleichbare Möglichkeit müsste es doch auch mit C++/Qt gebe, oder?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Luftballon hat geschrieben:In den Qt's Classes (http://doc.trolltech.com/4.5/classes.html) kann ich QVariantList nicht finden.
http://doc.trolltech.com/4.5.1/qvariant ... st-typedef
Und was ist die Funktion diesen Angangs ": m_question(question), m_answers(answers)" ?
Stichwort "Elementinitialisierer". Ich hab einfach angenommen, du hast in deiner Klasse auch membervariablen, die die Frage und die Antworten aufnehmen.
Mit PHP kann man alle Felder eines Datensatzes in ein Array schreiben und dann dieses Array einer Funktion übergeben. Das würde beispielsweise so aussehen:[...]

Eine vergleichbare Möglichkeit müsste es doch auch mit C++/Qt gebe, oder?
Ja, mit einer Liste. QList, std::list, std::vector, ganz nach deinem Gusto.
Du kannst auch ein QMap verwenden, dann hast du so was ähnliches wie dein assoziatives Array in PHP, wenn du QString als Key verwendest ;)
Luftballon
Beiträge: 29
Registriert: 10. Mai 2009 20:03

Beitrag von Luftballon »

Ah super, vielen Dank! Das schaue ich mir morgen/übermorgen mal alles genauer an. :-)
Luftballon
Beiträge: 29
Registriert: 10. Mai 2009 20:03

Beitrag von Luftballon »

Ich habe mir gerade mal QList, QMap und QHash angeschaut. Aktuell würde ich QHash bevorzugen, da ich in diesem Fall keine Sortierung benötige.

Der Schlüssel wäre bei mir vom Typ QString und auch die Werte wären vom Typ QString. So wie ich das aktuell blicke, können die Werte nur von einem Typ sein und es gibt mit Qt keinen Container, der Werte verschiedenen Typs aufnehmen kann, ist das richtig?

Und gibt es noch eine elegantere Möglichkeit als diese, um den QHash mit den Datenbankfeldern zu füllen:

Code: Alles auswählen

QSqlQuery query;
query.exec("SELECT * FROM question");
QSqlRecord record = query.record();
while( query.next() ) {
	QHash<QString, QString> hash;
	hash.insert("question", query.value(record.indexOf("question")).toString());
	hash.insert("answer_1", query.value(record.indexOf("answer_1")).toString());
	hash.insert("answer_2", query.value(record.indexOf("answer_2")).toString());
	hash.insert("answer_3", query.value(record.indexOf("answer_3")).toString());
	hash.insert("answer_4", query.value(record.indexOf("answer_4")).toString());
	hash.insert("answer_5", query.value(record.indexOf("answer_5")).toString());			
	qDebug() << "Anzahl: " << hash.size();
}
???

Auf jeden Fall würde es auf diese Weise schon sehr gut funktionieren! :-)

Wie würde dies denn ein erfahrener Qt-Programmierer lösen? Gibt's da noch ganz andere Möglichkeiten?

Würde mich sehr über "Erfahrungs-Tipps" freuen!

Beste Grüße,
der Luftballon
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Luftballon hat geschrieben:So wie ich das aktuell blicke, können die Werte nur von einem Typ sein und es gibt mit Qt keinen Container, der Werte verschiedenen Typs aufnehmen kann, ist das richtig?
Ich hab doch schon den Link zur Doku von QVariant gepostet :P
// hint //

Code: Alles auswählen

QHash<QString, QVariant> variantAnswers;
Luftballon
Beiträge: 29
Registriert: 10. Mai 2009 20:03

Beitrag von Luftballon »

*ein Licht geht auf* :-)

Es funktioniert tadellos - vielen Dank für die tolle Hilfe!
Antworten