Ejemplo de mapeador de widgets SQL
El ejemplo de mapeador de widgets SQL muestra cómo utilizar un mapeo de información desde una base de datos a los widgets de un formulario.

En el Ejemplo de Mapeador de Widgets Combo, mostramos cómo utilizar un mapeo con nombre entre un mapeador de widgets y un widget QComboBox con un modelo de propósito especial para relacionar valores en el modelo con una lista de opciones.
De nuevo, creamos una clase Window con una interfaz de usuario casi idéntica, proporcionando un cuadro combinado para permitir clasificar sus direcciones como "Casa", "Trabajo" u "Otro". Sin embargo, en lugar de utilizar un modelo separado para almacenar estos tipos de direcciones, utilizamos una tabla de base de datos para almacenar los datos del ejemplo y otra para almacenar los tipos de direcciones. De este modo, almacenamos toda la información en el mismo lugar.
Definición de la clase Window
La clase proporciona un constructor, una ranura para mantener los botones actualizados y una función privada para configurar el modelo:
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; };
Además del objeto QDataWidgetMapper y los controles utilizados para componer la interfaz de usuario, utilizamos un QStandardItemModel para mantener nuestros datos y un QStringListModel para mantener la información sobre los tipos de dirección que se pueden aplicar a los datos de cada persona.
Implementación de la clase Window
El primer acto realizado por el constructor de la clase Window es configurar el modelo utilizado para contener los datos del ejemplo. Dado que esta es una parte clave del ejemplo, veremos esto primero.
El modelo se inicializa en la función setupModel() de la ventana. Aquí, creamos una base de datos SQLite que contiene una tabla "persona" con campos de clave primaria, nombre, dirección y tipo.
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)");
En cada fila de la tabla, insertamos valores por defecto para estos campos, incluyendo valores para los tipos de dirección que corresponden a los tipos de dirección se almacenan en una tabla separada.

Creamos una tabla "addresstype" que contiene los identificadores utilizados en la tabla "person" y las cadenas correspondientes:
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(); }
El campo "typeid" de la tabla "person" se relaciona con el contenido de la tabla "addresstype" a través de una relación en QSqlRelationalTableModel. Este tipo de modelo realiza todo el trabajo necesario para almacenar los datos en una base de datos y también permite utilizar cualquier relación como modelo por derecho propio.
En este caso, hemos definido una relación para el campo "typeid" de la tabla "person" que lo relaciona con el campo "id" de la tabla "addresstype" y que hace que el contenido del campo "description" se utilice siempre que el "typeid" se presente al usuario. (Para más detalles, consulte la documentación de QSqlRelationalTableModel::setRelation()).

El constructor de la clase Window puede explicarse en tres partes. En la primera parte, configuramos el modelo utilizado para contener los datos y, a continuación, configuramos los widgets utilizados para la interfaz de usuario:
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);
Obtenemos un modelo para el cuadro combinado a partir del modelo principal, basado en la relación que establecimos para el campo "typeid". La llamada al cuadro combinado setModelColumn() selecciona el campo en el campo del modelo a mostrar.
Tenga en cuenta que este enfoque es similar al utilizado en el Ejemplo de mapeador de widgets de combo, en el que configuramos un modelo para el cuadro combinado. Sin embargo, en este caso, obtenemos un modelo basado en una relación en QSqlRelationalTableModel en lugar de crear uno por separado.
A continuación, configuramos el mapeador de widgets, relacionando cada widget de entrada con un campo del modelo:
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);
Para el cuadro combinado, ya conocemos el índice del campo en el modelo a partir de la función setupModel(). Utilizamos un QSqlRelationalDelegate como proxy entre el mapeador y los widgets de entrada para hacer coincidir los valores "typeid" del modelo con los del modelo del cuadro combinado y rellenarlo con descripciones en lugar de valores enteros.
Como resultado, el usuario puede seleccionar un elemento del cuadro combinado, y el valor asociado se escribe de nuevo en el modelo.
El resto del constructor establece las conexiones y los diseños:
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(); }
Mostramos la implementación de la ranura updateButtons() para completar:
void Window::updateButtons(int row) { previousButton->setEnabled(row > 0); nextButton->setEnabled(row < model->rowCount() - 1); }
Resumen y lecturas adicionales
El uso de un modelo separado para el cuadro combinado y un delegado especial para el mapeador de widgets nos permite presentar un menú de opciones al usuario. Aunque las opciones se almacenan en la misma base de datos que los datos del usuario, se guardan en una tabla independiente. Utilizando este enfoque, podemos reconstruir registros completos en un momento posterior mientras utilizamos adecuadamente las características de la base de datos.
Si no se utilizan modelos SQL, es posible utilizar más de un modelo para presentar las opciones al usuario. Esto está cubierto por el ejemplo Combo Widget Mapper.
© 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.