Wie kann ich ein QDateEdit mit DB-Inhalt füllen ??

Alles rund um die Programmierung mit Qt
Antworten
BenOtt
Beiträge: 13
Registriert: 3. März 2015 13:58

Wie kann ich ein QDateEdit mit DB-Inhalt füllen ??

Beitrag von BenOtt »

Wer kann mir sagen, wie ich ein Datum (01.01.2015) aus meiner SQLite-Datenbank in ein QDateEdit bekomme?
Wenn ich mein QDateEdit auf das Tagesdatum setze funktioniert es.

Code: Alles auswählen

QDate date = QDate::currentDate();
ui->qDateEdit->setDate(date); 
Wenn ich jedoch aus einer TableView das Datum übertragen will funktioniert es nicht.

Code: Alles auswählen

QDate  heute = qry.value(3).toDate();    // "heute" ist im Debugger invalid  Was ist falsch ???
ui->qDateEdit->setDate(heute); 
übertrage ich jedoch mein Feld aus der TableView in ein LineEdit dann steht dort das richtige Datum.

Code: Alles auswählen

ui->LineEdit->setText(qry.value(3).toString()); 
Vielleicht kann mir ja jemand helfen um dies zu bewerkstelligen.

Danke.
Ben
MfG
Ben
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Wie kann ich ein QDateEdit mit DB-Inhalt füllen ??

Beitrag von Christian81 »

Ist der Datentyp in der Tabelle auch ein Datum? Oder ein String?
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
BenOtt
Beiträge: 13
Registriert: 3. März 2015 13:58

Re: Wie kann ich ein QDateEdit mit DB-Inhalt füllen ??

Beitrag von BenOtt »

Der Datentyp ist ein Datum.
MfG
Ben
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Wie kann ich ein QDateEdit mit DB-Inhalt füllen ??

Beitrag von Christian81 »

Dann schreib mal bitte ein kurzes Testprogramm (kann ja eine in-memory sqlitedb sein, ohne GUI-Ausgabe) um das Problem aufzuzeigen.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
BenOtt
Beiträge: 13
Registriert: 3. März 2015 13:58

Re: Wie kann ich ein QDateEdit mit DB-Inhalt füllen ??

Beitrag von BenOtt »

Ich habe ein kleines Testprogramm mit einer Gui geschrieben, da ich die Probleme ja bei der Datenübertragung von der TableView in meine Eingabefelder habe.

Code: Alles auswählen

 main.cpp

#include "dialog.h"
#include <QApplication>
#include <QtSql>
#include <QMessageBox>
#include <QProgressDialog>
#include <cstdlib>
bool createConnection()
{
    QSqlDatabase myDB = QSqlDatabase::addDatabase("QSQLITE");
    myDB.setDatabaseName("TestDB.db");
    if (!myDB.open()) {
        QMessageBox::warning(0, QObject::tr("Database Error"),  myDB.lastError().text());
        return false;
    }
    return true;
}
void createDatabase()
{
    QProgressDialog progress;
    progress.setWindowModality(Qt::WindowModal);
    progress.setWindowTitle(QObject::tr("Datumstest"));
    progress.setLabelText(QObject::tr("Creating database..."));
    progress.setMinimum(0);
    progress.setValue(1);
    qApp->processEvents();
    QSqlQuery query;
    query.exec("DROP TABLE DatumTest");
    progress.setValue(4);
    qApp->processEvents();
    query.exec("CREATE TABLE DatumTest ("
               "lfdNr INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "
               "startDatum DATE NOT NULL, "
               "bewegungsDatum DATE NOT NULL, "
               "bezeichnung VARCHAR(20) ) ");
}
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    bool existingData = QFile::exists("TestDB.db");
    if (!createConnection())
        return 1;
    if (!existingData)
        createDatabase();
    Dialog w;
    w.show();
    return a.exec();
} 

Code: Alles auswählen

 dialog.h

#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QDebug>
#include <QFileInfo>
#include <QtSql>
#include <QSqlError>
#include <QMessageBox>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
    Q_OBJECT
public:
    QSqlDatabase myDB;
    bool connOpen()
    {
        myDB = QSqlDatabase::addDatabase("QSQLITE");
        myDB.setDatabaseName("TestDB.db");
        if(myDB.open())
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    void connClose()
    {
        myDB.close();
        myDB.removeDatabase(QSqlDatabase::defaultConnection);
    }
    // TabelView mit Daten füllen
    void fillTableView();
private:
    // Hilfsfelder
    QString xhDatum1, xhDatum2, xhBezeichnung, xhHeute;
public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();
private slots:
    void on_btnSave_clicked();
    void on_tableView_activated(const QModelIndex &index);
private:
    Ui::Dialog *ui;
}; 

Code: Alles auswählen

 Dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    if(connOpen())
    {
        fillTableView();
        ui->deDatum01->setFocus();
        ui->txtStatus->setText("verbunden mit DB....");
    }
    else
    {
        ui->txtStatus->setText("keine Verbindung möglich !!!");
    }
}
Dialog::~Dialog()
{
    connClose();
    delete ui;
}
void Dialog::fillTableView()
{
    QSqlQueryModel *model = new QsqlQueryModel();
    QSqlQuery *qry = new QSqlQuery(myDB);
    qry->prepare("select lfdNr, startDatum, bewegungsDatum, bezeichnung from DatumTest");
    qry->exec();
    model->setQuery(*qry);
    // Spaltenüberschrift
    model->setHeaderData(0, Qt::Horizontal, tr("lfdNr"));
    model->setHeaderData(1, Qt::Horizontal, tr("Datum 1"));
    model->setHeaderData(2, Qt::Horizontal, tr("Datum 2"));
    model->setHeaderData(3, Qt::Horizontal, tr("Bezeichnung"));
    ui->tableView->setModel(model);
    ui->tableView->setColumnWidth(0, 60);
    ui->tableView->setColumnWidth(1, 80);
    ui->tableView->setColumnWidth(2, 80);
    ui->tableView->setColumnWidth(3, 120);
}
void Dialog::on_btnSave_clicked()
{
    //
    xhDatum1       = ui->deDatum01->text();
    xhDatum2       = ui->deDatum02->text();
    xhBezeichnung  = ui->frmBezeichnung->text();
    if(!connOpen())
    {
        ui->txtStatus->setText("keine Verbindung möglich !!!");
        return;
    }
    QSqlQuery qry;
    qry.prepare("INSERT INTO DatumTest (startDatum, bewegungsDatum, bezeichnung) VALUES ('"+xhDatum1+"', '"+xhDatum2+"', '"+xhBezeichnung+"')");
    if(qry.exec())
    {
        fillTableView();
        QMessageBox::critical(this, tr("Speichern"), tr("Daten sind gespeichert"));
    }
    else
    {
        QMessageBox::warning(this, tr("Fehler beim Speichern"),qry.lastError().text());
    }
}
void Dialog::on_tableView_activated(const QModelIndex &index)
{
    QString xhSelect = ui->tableView->model()->data(index).toString();
    if (!connOpen())
    {
        ui->txtStatus->setText("keine DB-Verbindung !!!");
        return;
    }
    // SQL-Zugriff auf die Datenbank
    QSqlQuery qry;
    qry.prepare("SELECT * FROM DatumTest WHERE lfdNr = '"+xhSelect+"' ");
    if(qry.exec())
    {
        while (qry.next())
        {
            ui->frmLfdNr->setText(qry.value(0).toString());
            xhHeute = (qry.value(1).toString());                           // enthält richtiges Datum im Debugger
            QDate  heute = qry.value(1).toDate();
            ui->deDatum01->setDate(heute);
            QDate date = QDate::currentDate();
            ui->deDatum02->setDate(date);                               // Tagesdatum richtig übertragen
            ui->frmBezeichnung->setText(qry.value(3).toString());
        }
    }
    else
    {
        QMessageBox::warning(this, tr("Fehler"),qry.lastError().text());
    }
} 
Der Dialog enthält 3 Eingabefelder (2x QDateEdit 1x LineEdit) sowie ein geschützes Feld für den Primary Key sowie eine TabelView.
Wenn ich einen Datensatz in derTableView auswähle, dann wird mir das Datum nicht in mein Eingabefeld übertragen.
In das zweite Datumfeld übertrage ich deshalb das Tagesdatum und dies funktioniert.
Wie bekomme ich das Datum aus der TableView in mein QDateEdit ?
Danke für weitere Hilfe!
MfG
Ben
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Wie kann ich ein QDateEdit mit DB-Inhalt füllen ??

Beitrag von Christian81 »

Also das Problem liegt beim Speichern. Du speicherst ganz einfach einen QString der ein für dich lesbares Datum enthält. Das ist aber definitiv nicht das, was QDate/QDateTime benötigt um daraus ein sinnvolles Datum zu erzeugen. Du solltest also korrekt ein QDateTime - Objekt beim Speichern benutzen anstatt einen QString:

Code: Alles auswählen

    QSqlQuery qry;
    qry.prepare("INSERT INTO DatumTest (startDatum, bewegungsDatum, bezeichnung) VALUES (:start, :bewegung, :descr)");
    qry.bindValue(":start", ui->deDatum01->dateTime());
    qry.bindValue(":bewegung", ui->deDatum02->dateTime());
    qry.bindValue(":end", ui->frmBezeichnung->text());
    if(qry.exec())
    ...
Eine andere Datenbank hätte Dir das wohl schon beim Insert um die Ohren gehauen, SQLite speichert intern alles als Text so dass dies hier nicht auffiel.


Und noch ein wenig Manöverkritik:
- Die UI-Datei war nicht mit dabei, das Problem an sich hätte wohl auch in einen 20-Zeiler in der main gezeigt werden können (Tabelle erzeugen, QDateTime so einfügren wie Du es tust, dies wieder auslesen und per qDebug() ausgeben)

- Zweimal memory-leak, qry muss in diesem Fall nichtmal per new erzeugt werden:

Code: Alles auswählen

void Dialog::fillTableView()
{
    QSqlQueryModel *model = new QSqlQueryModel();
    QSqlQuery *qry = new QSqlQuery(myDB);
    ...
- Hier erzeugst du jedes Mal eine neue Datenbankverbindung (und schließt die alte) - komplett unnötig. Einfach auf die DB mit QSqlDatabase::database() zugreifen. Deshalb musst Du in fillTableView auch immer wieder ein neues Model etc. erzeugen was normalerweise unnötig ist:

Code: Alles auswählen

bool connOpen()
{
    myDB = QSqlDatabase::addDatabase("QSQLITE");
    myDB.setDatabaseName("TestDB.db");
    if(myDB.open())
    ....
}
- Es ist nirgends definiert, welche Spalte wann zurückgeliefert wird. Demnach immer angeben was man will:

Code: Alles auswählen

qry.prepare("SELECT * FROM DatumTest WHERE lfdNr = '"+xhSelect+"' ");
-->
qry.prepare("SELECT lfdNr, startDatum, bewegungsDatum, bezeichnung FROM DatumTest WHERE lfdNr = '"+xhSelect+"' ");
- Ein QSqlQueryModel ist zwar für einfachste Dinge gut aber wenn es was größeres werden soll würde ich eher ein cusom-Model benutzen.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
BenOtt
Beiträge: 13
Registriert: 3. März 2015 13:58

Re: Wie kann ich ein QDateEdit mit DB-Inhalt füllen ??

Beitrag von BenOtt »

Danke für die Hilfe!
Jetzt kann ich auch das Datum von der TableView in mein QDateEdit übertragen.

Was mich noch stört ist die Darstellung des Datums. In dem QDateEdit habe ich das Format ( tt.mm.yyyy ) in der Datenbank und anschließend in der TableView habe ich allerdings ein anderes Format ( yyyy-mm-tt ), was ich gern in die bei uns übliche Schreibweise ändern möchte.
Wie kann ich das machen, so dass ich das Format aus dem QDateEdit auch in die Datenbank schreiben kann.

Vielen Dank auch für die anderen Hinweise.
Ben
MfG
Ben
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Wie kann ich ein QDateEdit mit DB-Inhalt füllen ??

Beitrag von Christian81 »

Das habe ich schon angedeutet was man machen kann (und sollte anstatt ein simples QSqlQueryModel zu benutzen) - ein eigenes Model um die Darstellung selbst zu beeinflussen. Ggf. geht hier auch ein QSortFilterProxyModel dazwischen.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
BenOtt
Beiträge: 13
Registriert: 3. März 2015 13:58

Re: Wie kann ich ein QDateEdit mit DB-Inhalt füllen ??

Beitrag von BenOtt »

Danke für Deine Antwort.
Christian81 hat geschrieben:Das habe ich schon angedeutet was man machen kann (und sollte anstatt ein simples QSqlQueryModel zu benutzen) - ein eigenes Model um die Darstellung selbst zu beeinflussen. Ggf. geht hier auch ein QSortFilterProxyModel dazwischen.
Den Hinweis mit dem eigenen Model habe ich scheinbar nicht richtig verstanden. Dann werde ich mich doch früher als geplant mit dem Erstellen eigener Models auseinander setzen. Eigentlich wollte ich damit noch etwas warten, bis ich etwas mehr von Qt verstanden habe.
Kannst Du mir ein Buch empfehlen das mir neben den Basics auch verschiedene Konzepte von Qt gut erklärt? Zur aktuellen Version gibt es so wie ich gesehen habe kein Buch. Macht es aus Deiner Sicht / Erfahrung Sinn sich ein älteres (zu Qt 4) zu kaufen? Nur mit der Dokumentation zu arbeiten ist gerade am Anfang etwas schwierig, da ich hier häufig den Wald vor lauter Bäumen nicht sehe.
Ich hoffe, dass ich auch bei weiteren Fragen (eines Freizeitentwicklers) den einen oder anderen hilfreichen Hinweis bekomme.
MfG
Ben
Antworten