SQL-Tabelle im Cache
Das Beispiel Cached Table zeigt, wie eine Tabellensicht verwendet werden kann, um auf eine Datenbank zuzugreifen und Änderungen an den Daten zwischenzuspeichern, bis der Benutzer sie explizit über eine Drucktaste eingibt.
Das Beispiel besteht aus einer einzigen Klasse, TableEditor
, die ein benutzerdefiniertes Dialog-Widget darstellt, mit dem der Benutzer in einer Datenbank gespeicherte Daten ändern kann. Wir werden zunächst die Klassendefinition und die Verwendung der Klasse besprechen und dann einen Blick auf die Implementierung werfen.
TableEditor Klassendefinition
Die Klasse TableEditor
erbt QWidget und macht das Tabelleneditor-Widget zu einem Dialogfenster der obersten Ebene.
class TableEditor : public QWidget { Q_OBJECT public: explicit TableEditor(const QString &tableName, QWidget *parent = nullptr); private slots: void submit(); private: QPushButton *submitButton; QPushButton *revertButton; QPushButton *quitButton; QDialogButtonBox *buttonBox; QSqlTableModel *model; };
Der TableEditor
Konstruktor nimmt zwei Argumente entgegen: Das erste ist ein Verweis auf die Datenbanktabelle, mit der das TableEditor
Objekt arbeiten wird. Das andere ist ein Zeiger auf das übergeordnete Widget und wird an den Konstruktor der Basisklasse weitergegeben.
Beachten Sie die QSqlTableModel Variablendeklaration: Wie wir in diesem Beispiel sehen werden, kann die Klasse QSqlTableModel verwendet werden, um Daten für Ansichtsklassen wie QTableView bereitzustellen. Die Klasse QSqlTableModel bietet ein editierbares Datenmodell, das das Lesen und Schreiben von Datenbankeinträgen aus einer einzigen Tabelle ermöglicht. Sie baut auf der untergeordneten Klasse QSqlQuery auf, die Mittel zur Ausführung und Bearbeitung von SQL-Anweisungen bereitstellt.
Wir werden auch zeigen, wie eine Tabellensicht verwendet werden kann, um Änderungen an den Daten zwischenzuspeichern, bis der Benutzer sie ausdrücklich anfordert. Aus diesem Grund müssen wir neben dem Modell und den Schaltflächen des Editors auch einen submit()
Slot deklarieren.
Verbindung zu einer Datenbank |
---|
Bevor wir die Klasse TableEditor verwenden können, müssen wir eine Verbindung zur Datenbank herstellen, die die Tabelle enthält, die wir bearbeiten wollen:int main(int argc, char *argv[]) { QApplication app(argc, argv); if (!createConnection()) return 1; TableEditor editor("person"); editor.show(); return app.exec(); } Die Funktion static bool createConnection() { QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName(":memory:"); if (!db.open()) { QMessageBox::critical(nullptr, QObject::tr("Cannot open database"), QObject::tr("Unable to establish a database connection.\n" "This example needs SQLite support. Please read " "the Qt SQL driver documentation for information how " "to build it.\n\n" "Click Cancel to exit."), QMessageBox::Cancel); return false; } QSqlQuery query; query.exec("create table person (id int primary key, " "firstname varchar(20), lastname varchar(20))"); query.exec("insert into person values(101, 'Danny', 'Young')"); query.exec("insert into person values(102, 'Christine', 'Holand')"); query.exec("insert into person values(103, 'Lars', 'Gordon')"); query.exec("insert into person values(104, 'Roberto', 'Robitaille')"); query.exec("insert into person values(105, 'Maria', 'Papadopoulos')"); query.exec("create table items (id int primary key," "imagefile int," "itemtype varchar(20)," "description varchar(100))"); query.exec("insert into items " "values(0, 0, 'Qt'," "'Qt is a full development framework with tools designed to " "streamline the creation of stunning applications and " "amazing user interfaces for desktop, embedded and mobile " "platforms.')"); query.exec("insert into items " "values(1, 1, 'Qt Quick'," "'Qt Quick is a collection of techniques designed to help " "developers create intuitive, modern-looking, and fluid " "user interfaces using a CSS & JavaScript like language.')"); query.exec("insert into items " "values(2, 2, 'Qt Creator'," "'Qt Creator is a powerful cross-platform integrated " "development environment (IDE), including UI design tools " "and on-device debugging.')"); query.exec("insert into items " "values(3, 3, 'Qt Project'," "'The Qt Project governs the open source development of Qt, " "allowing anyone wanting to contribute to join the effort " "through a meritocratic structure of approvers and " "maintainers.')"); query.exec("create table images (itemid int, file varchar(20))"); query.exec("insert into images values(0, 'images/qt-logo.png')"); query.exec("insert into images values(1, 'images/qt-quick.png')"); query.exec("insert into images values(2, 'images/qt-creator.png')"); query.exec("insert into images values(3, 'images/qt-project.png')"); return true; } Die Funktion |
Implementierung der TableEditor-Klasse
Die Klassenimplementierung besteht nur aus zwei Funktionen, dem Konstruktor und dem Slot submit()
. Im Konstruktor erstellen wir das Datenmodell und die verschiedenen Fensterelemente und passen sie an:
TableEditor::TableEditor(const QString &tableName, QWidget *parent) : QWidget(parent) { model = new QSqlTableModel(this); model->setTable(tableName); model->setEditStrategy(QSqlTableModel::OnManualSubmit); model->select(); model->setHeaderData(0, Qt::Horizontal, tr("ID")); model->setHeaderData(1, Qt::Horizontal, tr("First name")); model->setHeaderData(2, Qt::Horizontal, tr("Last name"));
Zunächst erstellen wir das Datenmodell und legen die SQL-Datenbanktabelle fest, mit der das Modell arbeiten soll. Beachten Sie, dass die Funktion QSqlTableModel::setTable() keine Daten aus der Tabelle auswählt, sondern nur deren Feldinformationen abruft. Aus diesem Grund rufen wir die Funktion QSqlTableModel::select() später auf, um das Modell mit Daten aus der Tabelle zu füllen. Die Auswahl kann durch die Angabe von Filtern und Sortierbedingungen angepasst werden (siehe die Dokumentation der Klasse QSqlTableModel für weitere Details).
Außerdem legen wir die Bearbeitungsstrategie für das Modell fest. Die Bearbeitungsstrategie bestimmt, wann die vom Benutzer in der Ansicht vorgenommenen Änderungen tatsächlich in die Datenbank übernommen werden. Da wir die Änderungen in der Tabellensicht (d. h. im Modell) zwischenspeichern wollen, bis der Benutzer sie explizit abschickt, wählen wir die Strategie QSqlTableModel::OnManualSubmit. Die Alternativen sind QSqlTableModel::OnFieldChange und QSqlTableModel::OnRowChange.
Schließlich richten wir die im Kopf der Ansicht angezeigten Beschriftungen mit der Funktion setHeaderData() ein, die das Modell von der Klasse QSqlQueryModel erbt.
QTableView *view = new QTableView; view->setModel(model); view->resizeColumnsToContents();
Dann erstellen wir eine Tabellenansicht. Die Klasse QTableView bietet eine Standard-Modell/View-Implementierung einer Tabellenansicht, d. h. sie implementiert eine Tabellenansicht, die Elemente aus einem Modell anzeigt. Sie ermöglicht es dem Benutzer auch, die Elemente zu bearbeiten und die Änderungen im Modell zu speichern. Um eine schreibgeschützte Ansicht zu erstellen, setzen Sie das entsprechende Flag mit der Eigenschaft editTriggers, die die Ansicht von der Klasse QAbstractItemView erbt.
Damit die Ansicht unsere Daten anzeigt, übergeben wir unser Modell mit der Funktion setModel() an die Ansicht.
submitButton = new QPushButton(tr("Submit")); submitButton->setDefault(true); revertButton = new QPushButton(tr("&Revert")); quitButton = new QPushButton(tr("Quit")); buttonBox = new QDialogButtonBox(Qt::Vertical); buttonBox->addButton(submitButton, QDialogButtonBox::ActionRole); buttonBox->addButton(revertButton, QDialogButtonBox::ActionRole); buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
Die Schaltflächen von TableEditor
sind normale QPushButton Objekte. Wir fügen sie zu einem Schaltflächenfeld hinzu, um sicherzustellen, dass die Schaltflächen in einem Layout dargestellt werden, das dem aktuellen Widget-Stil angemessen ist. Der Grund dafür ist, dass Dialoge und Nachrichtenboxen normalerweise Schaltflächen in einem Layout darstellen, das den Schnittstellenrichtlinien für diese Plattform entspricht. Es ist unvermeidlich, dass verschiedene Plattformen unterschiedliche Layouts für ihre Dialoge haben. QDialogButtonBox ermöglicht es einem Entwickler, Schaltflächen hinzuzufügen und verwendet automatisch das passende Layout für die Desktop-Umgebung des Benutzers.
Die meisten Schaltflächen für einen Dialog folgen bestimmten Rollen. Wenn eine Schaltfläche mit der Funktion addButton() zu einem Schaltflächenfeld hinzugefügt wird, muss die Rolle der Schaltfläche mit dem Enum QDialogButtonBox::ButtonRole angegeben werden. Alternativ dazu bietet QDialogButtonBox mehrere Standardschaltflächen (z. B. OK, Cancel, Save), die Sie verwenden können. Sie existieren als Flags, so dass Sie sie im Konstruktor mit ODER verknüpfen können.
connect(submitButton, &QPushButton::clicked, this, &TableEditor::submit); connect(revertButton, &QPushButton::clicked, model, &QSqlTableModel::revertAll); connect(quitButton, &QPushButton::clicked, this, &TableEditor::close);
Wir verbinden die Schaltfläche Quit mit dem Slot close() des Tabelleneditors und die Schaltfläche Submit mit unserem privaten Slot submit()
. Der letztgenannte Slot wird sich um die Datentransaktionen kümmern. Schließlich verbinden wir die Schaltfläche Revert mit dem Slot revertAll() unseres Modells, um alle anstehenden Änderungen rückgängig zu machen (d. h. die ursprünglichen Daten wiederherzustellen).
QHBoxLayout *mainLayout = new QHBoxLayout; mainLayout->addWidget(view); mainLayout->addWidget(buttonBox); setLayout(mainLayout); setWindowTitle(tr("Cached Table")); }
Zum Schluss fügen wir das Schaltflächenfeld und die Tabellenansicht zu einem Layout hinzu, installieren das Layout auf dem Tabelleneditor-Widget und setzen den Fenstertitel des Editors.
void TableEditor::submit() { model->database().transaction(); if (model->submitAll()) { model->database().commit(); } else { model->database().rollback(); QMessageBox::warning(this, tr("Cached Table"), tr("The database reported an error: %1") .arg(model->lastError().text())); } }
Der Slot submit()
wird immer dann aufgerufen, wenn die Benutzer auf die Schaltfläche Submit klicken, um ihre Änderungen zu speichern.
Zunächst wird mit der Funktion QSqlDatabase::transaction() eine Datenbanktransaktion gestartet. Eine Datenbanktransaktion ist eine Einheit der Interaktion mit einem Datenbankverwaltungssystem oder einem ähnlichen System, die unabhängig von anderen Transaktionen auf kohärente und zuverlässige Weise behandelt wird. Ein Zeiger auf die verwendete Datenbank kann mit der Funktion QSqlTableModel::database() ermittelt werden.
Anschließend versuchen wir, alle ausstehenden Änderungen, d. h. die geänderten Elemente des Modells, zu übertragen. Wenn kein Fehler auftritt, wird die Transaktion mit der Funktion QSqlDatabase::commit() an die Datenbank übertragen (beachten Sie, dass diese Funktion bei einigen Datenbanken nicht funktioniert, wenn eine QSqlQuery auf der Datenbank aktiv ist). Andernfalls führen wir mit der Funktion QSqlDatabase::rollback() einen Rollback der Transaktion durch und geben eine Warnung an den Benutzer aus.
Siehe auch: Eine vollständige Liste der SQL-Datenbankklassen von Qt und die Dokumentation zur Model/View-Programmierung. |
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.