Beispiel für den SQL-Widget-Mapper
Das Beispiel zum SQL-Widget-Mapper zeigt, wie man Informationen aus einer Datenbank auf Widgets in einem Formular abbildet.

Im Beispiel zum Combo-Widget-Mapper haben wir gezeigt, wie man eine benannte Zuordnung zwischen einem Widget-Mapper und einem „ QComboBox “-Widget mit einem speziellen Zweckmodell verwendet, um Werte im Modell mit einer Auswahlliste zu verknüpfen.
Auch hier erstellen wir eine „ Window “-Klasse mit einer nahezu identischen Benutzeroberfläche, die ein Kombinationsfeld bereitstellt, über das Adressen als „Zuhause“, „Arbeit“ oder „Sonstiges“ klassifiziert werden können. Anstatt jedoch ein separates Modell zur Speicherung dieser Adresstypen zu verwenden, nutzen wir eine Datenbanktabelle für die Beispieldaten und eine weitere für die Adresstypen. Auf diese Weise speichern wir alle Informationen an einem Ort.
Definition der Fensterklasse
Die Klasse verfügt über einen Konstruktor, einen Slot zur Aktualisierung der Schaltflächen und eine private Funktion zum Einrichten des Modells:
class Window : public QWidget
{
Q_OBJECT
public:
Window(QWidget *parent = nullptr);
private slots:
void updateButtons(int row);
private:
void setupModel();
QLabel *nameLabel;
QLabel *addressLabel;
QLabel *typeLabel;
QLineEdit *nameEdit;
QTextEdit *addressEdit;
QComboBox *typeComboBox;
QPushButton *nextButton;
QPushButton *previousButton;
QSqlRelationalTableModel *model;
QItemSelectionModel *selectionModel;
QDataWidgetMapper *mapper;
int typeIndex;
};Zusätzlich zum „ QDataWidgetMapper “-Objekt und den Steuerelementen, aus denen sich die Benutzeroberfläche zusammensetzt, verwenden wir ein „QStandardItemModel“ zur Speicherung unserer Daten und ein „ QStringListModel “, um Informationen über die Adresstypen zu speichern, die auf die Daten jeder Person angewendet werden können.
Implementierung der Fensterklasse
Als Erstes richtet der Konstruktor der Klasse ` Window ` das Modell ein, in dem die Beispieldaten gespeichert werden. Da dies ein zentraler Bestandteil des Beispiels ist, werden wir uns dies zunächst ansehen.
Das Modell wird in der Funktion „ setupModel() “ des Fensters initialisiert. Hier erstellen wir eine SQLite-Datenbank, die eine Tabelle „person“ mit den Feldern Primärschlüssel, Name, Adresse und Typ enthält.
void Window::setupModel()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":memory:");
if (!db.open()) {
QMessageBox::critical(0, tr("Cannot open database"),
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."), QMessageBox::Cancel);
return;
}
QSqlQuery query;
query.exec("create table person (id int primary key, "
"name varchar(20), address varchar(200), typeid int)");
query.exec("insert into person values(1, 'Alice', "
"'<qt>123 Main Street<br/>Market Town</qt>', 101)");
query.exec("insert into person values(2, 'Bob', "
"'<qt>PO Box 32<br/>Mail Handling Service"
"<br/>Service City</qt>', 102)");
query.exec("insert into person values(3, 'Carol', "
"'<qt>The Lighthouse<br/>Remote Island</qt>', 103)");
query.exec("insert into person values(4, 'Donald', "
"'<qt>47338 Park Avenue<br/>Big City</qt>', 101)");
query.exec("insert into person values(5, 'Emma', "
"'<qt>Research Station<br/>Base Camp<br/>"
"Big Mountain</qt>', 103)");In jede Zeile der Tabelle fügen wir Standardwerte für diese Felder ein, einschließlich der Werte für die Adresstypen, die den in einer separaten Tabelle gespeicherten Adresstypen entsprechen.

Wir erstellen eine Tabelle „addresstype“, die die in der Tabelle „person“ verwendeten Identifikatoren und die entsprechenden Zeichenfolgen enthält:
query.exec("create table addresstype (id int, description varchar(20))");
query.exec("insert into addresstype values(101, 'Home')");
query.exec("insert into addresstype values(102, 'Work')");
query.exec("insert into addresstype values(103, 'Other')");
model = new QSqlRelationalTableModel(this);
model->setTable("person");
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
typeIndex = model->fieldIndex("typeid");
model->setRelation(typeIndex,
QSqlRelation("addresstype", "id", "description"));
model->select();
}Das Feld „typeid“ in der Tabelle „person“ ist über eine Relation in einem „ QSqlRelationalTableModel “ mit dem Inhalt der Tabelle „addresstype“ verknüpft. Diese Art von Modell übernimmt alle notwendigen Aufgaben zur Speicherung der Daten in einer Datenbank und ermöglicht es zudem, beliebige Relationen als eigenständige Modelle zu verwenden.
In diesem Fall haben wir für das Feld „typeid“ in der Tabelle „person“ eine Relation definiert, die es mit dem Feld „id“ in der Tabelle „addresstype“ verknüpft und bewirkt, dass der Inhalt des Feldes „description“ überall dort verwendet wird, wo die „typeid“ dem Benutzer angezeigt wird. (Einzelheiten finden Sie in der Dokumentation zu ` QSqlRelationalTableModel::setRelation()`.)

Der Konstruktor der Klasse ` Window ` lässt sich in drei Teile untergliedern. Im ersten Teil richten wir das Modell ein, in dem die Daten gespeichert werden, anschließend richten wir die Widgets für die Benutzeroberfläche ein:
Window::Window(QWidget *parent)
: QWidget(parent)
{
setupModel();
nameLabel = new QLabel(tr("Na&me:"));
nameEdit = new QLineEdit();
addressLabel = new QLabel(tr("&Address:"));
addressEdit = new QTextEdit();
typeLabel = new QLabel(tr("&Type:"));
typeComboBox = new QComboBox();
nextButton = new QPushButton(tr("&Next"));
previousButton = new QPushButton(tr("&Previous"));
nameLabel->setBuddy(nameEdit);
addressLabel->setBuddy(addressEdit);
typeLabel->setBuddy(typeComboBox);Wir leiten ein Modell für die Kombinationsfeld aus dem Hauptmodell ab, basierend auf der Relation, die wir für das Feld „typeid“ eingerichtet haben. Der Aufruf von ` setModelColumn()` für das Kombinationsfeld wählt das Feld im Modell aus, das angezeigt werden soll.
Beachten Sie, dass dieser Ansatz dem im Beispiel „Combo Widget Mapper“ verwendeten ähnelt, da wir ein Modell für die Kombinationsliste einrichten. In diesem Fall leiten wir das Modell jedoch aus einer Beziehung im ` QSqlRelationalTableModel ` ab, anstatt ein separates Modell zu erstellen.
Als Nächstes richten wir den Widget-Mapper ein und ordnen jedes Eingabe-Widget einem Feld im Modell zu:
QSqlTableModel *relModel = model->relationModel(typeIndex);
typeComboBox->setModel(relModel);
typeComboBox->setModelColumn(relModel->fieldIndex("description"));
mapper = new QDataWidgetMapper(this);
mapper->setModel(model);
mapper->setItemDelegate(new QSqlRelationalDelegate(this));
mapper->addMapping(nameEdit, model->fieldIndex("name"));
mapper->addMapping(addressEdit, model->fieldIndex("address"));
mapper->addMapping(typeComboBox, typeIndex);Für die Kombinationsbox kennen wir den Index des Feldes im Modell bereits aus der Funktion „ setupModel() “. Wir verwenden ein „ QSqlRelationalDelegate “ als Vermittler zwischen dem Mapper und den Eingabe-Widgets, um die „typeid“-Werte im Modell mit denen im Modell der Kombinationsbox abzugleichen und die Kombinationsbox mit Beschreibungen statt mit ganzzahligen Werten zu füllen.
Dadurch kann der Benutzer einen Eintrag aus der Kombinationsbox auswählen, und der zugehörige Wert wird zurück ins Modell geschrieben.
Der Rest des Konstruktors richtet Verbindungen und Layouts ein:
connect(previousButton, &QPushButton::clicked,
mapper, &QDataWidgetMapper::toPrevious);
connect(nextButton, &QPushButton::clicked,
mapper, &QDataWidgetMapper::toNext);
connect(mapper, &QDataWidgetMapper::currentIndexChanged,
this, &Window::updateButtons);
QGridLayout *layout = new QGridLayout();
layout->addWidget(nameLabel, 0, 0, 1, 1);
layout->addWidget(nameEdit, 0, 1, 1, 1);
layout->addWidget(previousButton, 0, 2, 1, 1);
layout->addWidget(addressLabel, 1, 0, 1, 1);
layout->addWidget(addressEdit, 1, 1, 2, 1);
layout->addWidget(nextButton, 1, 2, 1, 1);
layout->addWidget(typeLabel, 3, 0, 1, 1);
layout->addWidget(typeComboBox, 3, 1, 1, 1);
setLayout(layout);
setWindowTitle(tr("SQL Widget Mapper"));
mapper->toFirst();
}Der Vollständigkeit halber zeigen wir die Implementierung des Slots „ updateButtons() “:
void Window::updateButtons(int row)
{
previousButton->setEnabled(row > 0);
nextButton->setEnabled(row < model->rowCount() - 1);
}Zusammenfassung und weiterführende Literatur
Die Verwendung eines separaten Modells für die Kombinationsfeld und eines speziellen Delegaten für den Widget-Mapper ermöglicht es uns, dem Benutzer ein Auswahlmenü anzubieten. Obwohl die Auswahlmöglichkeiten in derselben Datenbank wie die Benutzerdaten gespeichert sind, werden sie in einer separaten Tabelle verwaltet. Mit diesem Ansatz können wir zu einem späteren Zeitpunkt vollständige Datensätze rekonstruieren und dabei die Datenbankfunktionen angemessen nutzen.
Auch wenn keine SQL-Modelle verwendet werden, ist es dennoch möglich, mehr als ein Modell zu nutzen, um dem Benutzer Auswahlmöglichkeiten anzubieten. Dies wird im Beispiel „Combo Widget Mapper“ behandelt.
© 2026 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.