Seite 1 von 1
[gelöst] Datenbankklasse und Signal Slot Prinzip
Verfasst: 21. Februar 2009 14:00
von Illuminatus
hi und zwar gehts darum, dass ich eine Oberfläche habe, die mithilfe eines von QT vorfefinierten Signals auf einer Datenbank verbindung die schon beim Konstruktor der Oberflächenklasse erstellt wird, eine Query absetzt.
wie kann ich nun also ein Slot in der Klasse connection definieren, so dass wenn die query abgesetzt wird gleichzeitig wieder ein Signal an die Oberfläche und den QTextEdit abgesetzt wird und darauf deas Ergebnistupel erscheint? also mir gehts eigentlich darum woher die klasse connection weiß dass es die oberfläche gibt`, bzw. die eine instanz davon?
Code: Alles auswählen
#ifndef CONNECTION_H
#define CONNECTION_H
#include <QtSql>
#include <QObject>
class connection : public QObject
{
Q_OBJECT
public:
connection(QString driver, QString hostname, QString databasename, QString user, QString password);
QSqlDatabase db;
public slots:
signals:
private:
};
#endif //CONNECTION_H
Code: Alles auswählen
#include "connection.h"
connection::connection(QString driver, QString hostname, QString databasename, QString user, QString password) {
db = QSqlDatabase::addDatabase(driver);
db.setHostName(hostname);
db.setDatabaseName(databasename);
db.setUserName(user);
db.setPassword(password);
bool okay = db.open();
}
Re: Datenbankklasse und Signal Slot Prinzip
Verfasst: 21. Februar 2009 20:22
von franzf
Illuminatus hat geschrieben:wie kann ich nun also ein Slot in der Klasse connection definieren, so dass wenn die query abgesetzt wird gleichzeitig wieder ein Signal an die Oberfläche und den QTextEdit abgesetzt wird und darauf deas Ergebnistupel erscheint?
Warum du eine zusätzliche Klasse "connection" brauchst, versteh ich nicht ganz, oder hast du da ein paar entscheidende Member weggelassen? Und dass db public ist, solltest du bei OOP eigentlich lassen (Stichwort "Datenkapselung").
Ansonsten hast du eigentlich kein wirkliches Problem (oder ich verstehs nicht). Denn ein QSqlQuery liefert dir sofort das Ergebnis des Query zurück, also gibts gar keinen Grund da erst Signals durch die Gegend zu schießen.
Verfasst: 21. Februar 2009 20:31
von Illuminatus
hi
hab ne extra klasse erstellt, da ich das ganze programm schön modular erstellen will. ist für ein seminar und soll später von den teilnehmern leicht verstanden werden. hab nun ein slot definiert, der auf die QLineEdit "sql_in" (als Eingabefeld für den query) und "sql_out" (QTextArea für Tupelwiedergabe) zugreift.
Code: Alles auswählen
//dbvis.cpp <--- von QMainWindow abgeleitete Klasse
void dbvis::query_slot(){
QString temp_anfrage = sql_in->text();
QString temp = "";
sql_in->setText("");
if(conn->db.open()) {
QSqlQuery query;
query.exec(temp_anfrage);
// ResultSet auslesen
while(query.next()){
temp.append(query.value(1).toString());
temp.append(" ");
}
}
sql_out->setText(temp);
}
Weist du/ Wisst ihr wie man es eventuell machen kann, dass er herausfindet welche Datentypen sich in den Tupelattributen befinden? also dass ich unabhängig von bestimmten Attributtypen jedes Anfrageergebnis auslesen kann?
Verfasst: 21. Februar 2009 21:25
von upsala
Die Datentypen findest du im QSqlRecord.
Und wenn das ganze für ein Seminar ist, dann solltest du mal an deiner Rechtschreibung und deinen Code-Konventionen arbeiten.
Verfasst: 21. Februar 2009 21:59
von franzf
Ein paar andere Sachen noch:
wenn connection wirklich nur benötigt wird, um das db-Object zu speichern, ist es absolut überflüssig. Das wird nämlich schon in QSqlDatabase gespeichert. Bei addDatabase kannst du noch nen Namen mitgeben, über den du dann die Database mittels QSqlDatabase::database(name) holen kannst. Und wenn du es unbedingt Speichern willst, kannst du das auch in deiner MainWindow-Klasse machen.
Implizit gehst du ja auch davon aus, dass du eine "defaultConnection" hast, denn QSqlQuery ohne Database im Konstruktor nimmt die default.
Dann solltest du dir überlegen, ob der ein oder andere Check vor dem Ausführen des Query nützlich sein könnte. Denn jetzt wird auch ein drop table oder delete ohne Kommentar ausgeführt.
Und nur den index "1" an den String anhängen (Für was gibt es eigentlich QStringList?!?) ist auch doof, wenn man explizit nach bestimmten Spalten fragt. Da werden die Seminarteilnehmer doof schauen, wenn die Query nicht das zurück gibt, was man will.
Verfasst: 22. Februar 2009 14:31
von Illuminatus
hi sorry war vllt missverständlich^^ ich bin teilnehmer des seminars und werde das programm präsentieren (müssen). also das mit den konventionen^^ ich weis

is nicht so prickeln, bin auch erst im 3.semester und komm eigentlich eher aus der java ecke. hab C++ auch extra wegen dem seminar mir ein bisschen angeeignet.
Also ich habe vor die ganzen Datentupel die mir diese Anfrage zurückwirft in eine ArrayList zu speichern. Dafür will ich dann einen extra Datentyp entwerfen der wiederum eine ArrayList jeweils für die einzelnen Elemente (Attribute des Tupels) innehat. Wie kann ich es nun also machen, dass das Programm zur Laufzeit entscheidet, als welchen Datentyp er die Objekte in die ArrayList eines Elements <Tupel> einfügt?
Ich hoffe ihr versteht was ich meine?
Verfasst: 22. Februar 2009 15:19
von franzf
Der query.record().value() ist doch ein QVariant, oder?
Ein QVariant hat eine wundervollbringende Methode "type()" über die du ohne weiteres den (na?) Typ ermitteln kannst
Im übrigen solltest du doch selbst die Definition deiner table kennen und somit auch, was drinnen steckt. Oder hab ich dich jetzt komplett falsch verstanden?
Verfasst: 22. Februar 2009 15:23
von Illuminatus
ja natürlich, aber das programm soll universell auf jede datenbank relation anwendbar sein, also nicht nur auf meine tabellen
danke ich versuch das mal zu implementieren =)
ich hab das mit dem QVariant bisher so verstanden dass das nur ein feld ist welches verschiedene datentypen definiert???
also versteh ich das richtig:
ich muss zuerst die anzahl der spalten feststellen?
dann durch diese durchiterieren und jedesmal muss ich dann doch feststellen welchem datentyp in Qt der sql-konforme entspricht! aber mit welchem befehl kann ich das machen?
lad ich die einfach als QVariant und finde mit type() den gleichwertigen raus?
Verfasst: 22. Februar 2009 15:34
von franzf
Illuminatus hat geschrieben:ich hab das mit dem QVariant bisher so verstanden dass das nur ein feld ist welches verschiedene datentypen definiert???
Verschiedene Datentypen definieren kann es sicher nicht.
Es "behebt" halt die feste Typisierung von C++ und die damit einhergehende Unfähigkeit, in einer Variable mehrere Typen abzuspeichern, so wie z.B. in den ganzen Scriptsprachen.
Um dann wieder an die korrekt typisierten Daten zu kommen, gibt es Methoden wie toString() usw.
Verfasst: 22. Februar 2009 15:48
von Illuminatus
ahh okay, das hat mir nun echt weitergeholfen!!! ich arbeit auch gerade mit dem assistenten und versuch das dort zu verstehen!
wenn ich also ein element QVariant hab, wie bekomm ich dann raus ob das zum beispiel ein integer ist, oder ein string?
klar ist das in den meisten fällen kein problem da ein integer au als string dargestellt wird, aber in komplexeren fällen weis man ja nie.
Habe folgendes im Assi gefunden und nun auf meine Bedürfnisse leicht verändert:
Code: Alles auswählen
QVariant v;
QString c;
if (v.canConvert<QString>())
c = v.value<QString>(v);
ist diese überprüfung korrekt?
Verfasst: 22. Februar 2009 15:56
von franzf
Das was du machst, bringt dich nciht wirklich darauf, was für ein Type drinstackt, sondern ob du ihn nach String konvertieren kannst, und das geht mit fast allen Typen.
Und um zu wissen, ob da grad ein int drinnensteckt, mach Folgendes:
Code: Alles auswählen
if( v.type() == QVariant::Int ) {
// irgend was schönes und dolles mit dem int anstellen
}
Schau dir halt einfach mal die ganzen Beispiele im assistant zu QVariant an.
Verfasst: 22. Februar 2009 17:47
von Illuminatus
lässt sich eigentlich über SqlQuery irgendiwe die anzahl der attribute (spalten) bestimmen?
hab dazu im assistenten nichts gefunden?
oder gibts eine schönere möglichkeit als
for(int i=0; i<ATTRIBUTE; i++)
{
container= result.value(i);
}
durch die attribute durchzugehen?
ich meine nicht die tupel!!! dafür gibts darüber nochmal ne schleife die bis result.size() läuft!
Verfasst: 22. Februar 2009 17:58
von franzf
Nimm dir doch einfach das erste record(), und speicher die size(). Das enthält die Anzahl der Spalten.
QSqlQuery::size() gibt ja nur die Anzahl der Zeilen.
Verfasst: 22. Februar 2009 18:05
von Illuminatus
jo so hab ichs nun gemacht
Code: Alles auswählen
if(result.size()!=-1)
{
while(result.next()){
for(int i=0;i<result.size(); i++)
{
tupel *current = new tupel(i);
for(int y=0; y<meta_result.count(); y++)
{
current->getAttributes.append(result.value(y));
}
}
}
}
Die tupelklasse enthält ein privates element QList<QVariant> in die ich nun die ganzen attribute eines ergebnistupels verpacken möchte...
er mosert mir allerdings urm, dass er links von append keine klasse hat?
bei mir is meta_result vom typ QSqlRecord und da stand dass irgendwie count() die anzahl wiedergibt?
FEHLER GEFUNDEN!!! Vieln dank für eure hilfe

Verfasst: 23. Februar 2009 08:19
von pfid
Warum packst du das ganze nicht einfach in eine QTableView und verwendest ein QSqlQueryModel oder QSqlTableModel? QTextEdit eignet sich nur bedingt zur Darstellung der Ergebnismenge, und bei View/Model brauchst du nichts händisch konvertieren.
Code: Alles auswählen
QTableView* view = new QTableView(...);
QSqlQueryModel* model = new QSqlQueryModel(...);
view->setModel(model);
model->setQuery("select foo from bar where ...");
oder
Code: Alles auswählen
QTableView* view = new QTableView(...);
QSqlTableModel* model = new QSqlTableModel(...);
view->setModel(model);
model->setTable("tb_seminar");
// ggfs:
model->setFilter("col_userid = 5");
model->select();