组合控件映射器示例
“下拉列表控件映射器”示例演示了如何使用QDataWidgetMapper 将模型中的信息映射到表单上的特定控件。

我们创建了一个Window 类,其用户界面几乎完全相同,唯一的区别在于:我们没有提供旋转框(spin box)来输入每个人的年龄,而是提供了一个下拉列表框(combo box),用于将地址分类为“家庭”、“工作”或“其他”。
Person 类定义
我们定义了一个名为 `Person ` 的结构体,其中包含姓名、地址和地址类型字段,用于表示模型数据:
struct Person
{
private:
Q_GADGET
Q_PROPERTY(QString name MEMBER name)
Q_PROPERTY(QString address MEMBER address)
Q_PROPERTY(QString type MEMBER type)
public:
QString name;
QString address;
QString type;
};将其声明为Q_GADGET 类型,其成员将作为同名属性,以便于填充QRangeModel 。
窗口类定义
该类提供了一个构造函数和一个槽,用于保持按钮状态的实时更新:
class Window : public QWidget
{
Q_OBJECT
public:
Window(QWidget *parent = nullptr);
private slots:
void updateButtons(int row);
private:
QLineEdit *nameEdit;
QTextEdit *addressEdit;
QComboBox *typeComboBox;
QPushButton *nextButton;
QPushButton *previousButton;
QList<Person> data;
QRangeModel *model;
QDataWidgetMapper *mapper;
};除了QDataWidgetMapper 对象和用于构建用户界面的控件外,我们还使用一个QList<Person>来存储数据,并使用QRangeModel 对其进行操作。
窗口类的实现
Window 类的构造函数可分为几个部分来解释。在第一部分中,我们初始化用于用户界面的控件:
Window::Window(QWidget *parent)
: QWidget(parent),
nameEdit(new QLineEdit),
addressEdit(new QTextEdit),
typeComboBox(new QComboBox),
nextButton(new QPushButton(tr("&Next"))),
previousButton(new QPushButton(tr("&Previous"))),人员列表通过初始化列表填充,然后将其传递给QRangeModel :
data{Person{u"Alice"_s, u"<qt>123 Main Street<br/>Market Town</qt>"_s, u"0"_s},
Person{u"Bob"_s, u"<qt>PO Box 32<br/>Mail Handling Service<br/>Service City</qt>"_s, u"1"_s},
Person{u"Carol"_s, u"<qt>The Lighthouse<br/>Remote Island</qt>"_s, u"2"_s},
Person{u"Donald"_s, u"<qt>47338 Park Avenue<br/>Big City</qt>"_s, u"0"_s},
Person{u"Emma"_s, u"<qt>Research Station<br/>Base Camp<br/>Big Mountain</qt>"_s, u"2"_s}},
model(new QRangeModel(data, this)),
mapper(new QDataWidgetMapper(this))请注意,我们以与其他控件相同的方式设置下拉列表的映射,但为其应用了专门的模型(该模型包含地址类型信息),这样它将显示地址类型字符串,而非包含每位人员数据的模型中的数据:
typeComboBox->setModel(new QStringListModel({ tr("Home"), tr("Work"), tr("Other") }, this));接下来,我们配置控件映射器,将每个输入控件与通过调用 `setModel()` 指定的模型中的一列建立关联:
mapper->setModel(model);
mapper->addMapping(nameEdit, 0);
mapper->addMapping(addressEdit, 1);
mapper->addMapping(typeComboBox, 2, "currentIndex");对于下拉列表,我们传递了一个额外参数,用于告知控件映射器应将哪个属性与模型中的值相关联。因此,用户可以从下拉列表中选择一个项目,而存储在控件currentIndex 属性中的对应值将被写入模型。
构造函数的其余部分用于设置连接和布局:
connect(previousButton, &QAbstractButton::clicked,
mapper, &QDataWidgetMapper::toPrevious);
connect(nextButton, &QAbstractButton::clicked,
mapper, &QDataWidgetMapper::toNext);
connect(mapper, &QDataWidgetMapper::currentIndexChanged,
this, &Window::updateButtons);
auto *formLayout = new QFormLayout;
formLayout->addRow(tr("Na&me:"), nameEdit);
formLayout->addRow(tr("&Address:"), addressEdit);
formLayout->addRow(tr("&Type:"), typeComboBox);
auto *buttonLayout = new QVBoxLayout;
buttonLayout->addWidget(previousButton);
buttonLayout->addWidget(nextButton);
buttonLayout->addStretch();
auto *mainLayout = new QHBoxLayout(this);
mainLayout->addLayout(formLayout);
mainLayout->addLayout(buttonLayout);
setWindowTitle(tr("Delegate Widget Mapper"));
mapper->toFirst();
}
为完整起见,我们展示updateButtons() 槽的实现:
void Window::updateButtons(int row)
{
previousButton->setEnabled(row > 0);
nextButton->setEnabled(row < model->rowCount() - 1);
}总结与进一步阅读
为下拉列表使用独立的模型,可以提供一个与主模型中存储的数据相互独立的选项菜单。通过使用命名映射将下拉列表的currentIndex 属性与模型中的某个列相关联,实际上允许我们在模型中存储一个查找值。
然而,当在小部件映射器(widget mapper)上下文之外读取模型时,我们需要了解“typeModel ”才能理解这些查找值。如果能将数据和“typeModel ”中包含的选项同时存储在一个地方,将会非常有用。这一点在“SQL 小部件映射器示例”中有所涉及。
© 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.