本页

组合部件映射器示例

组合部件映射器示例展示了如何使用QDataWidgetMapper 将模型中的信息映射到表单上的特定部件。

带有姓名、地址和类型等各种字段的应用程序

我们创建了一个Window 类,该类的用户界面几乎完全相同,不同的是,我们没有提供一个旋转框来输入每个人的年龄,而是提供了一个组合框来将他们的地址分为 "家庭"、"工作 "或 "其他"。

人员类定义

我们定义了一个包含姓名、地址和地址类型的结构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");

对于组合框,我们会传递一个额外参数,告诉窗口部件映射器哪个属性与模型中的值相关。因此,用户可以从组合框中选择一个项目,而存储在 widget 的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 属性与模型中的列相关联,可以有效地在模型中存储查找值。

但是,当在部件映射器的上下文之外读取模型时,我们需要了解typeModel ,以便理解这些查找值。如果能将typeModel 中的数据和选择存储在一个地方,那将会非常有用。SQL Widget Mapper 示例就涵盖了这一点。

示例项目 @ code.qt.io

© 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.