组合部件映射器示例
组合部件映射器示例展示了如何使用自定义委托将模型中的信息映射到表单上的特定部件。
我们创建了一个Window
类,该类的用户界面几乎完全相同,不同的是,我们没有提供一个旋转框来输入每个人的年龄,而是提供了一个组合框来将他们的地址分为 "家庭"、"工作 "或 "其他"。
窗口类定义
该类提供了一个构造函数、一个用于更新按钮的槽和一个用于设置模型的私有函数:
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; QStandardItemModel *model; QStringListModel *typeModel; QDataWidgetMapper *mapper; };
除了QDataWidgetMapper 对象和用于构成用户界面的控件外,我们还使用QStandardItemModel 来保存数据,并使用QStringListModel 来保存可应用于每个人数据的地址类型信息。
窗口类的实现
Window
类的构造函数可以分为三部分来解释。在第一部分中,我们设置了用于用户界面的部件:
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); typeComboBox->setModel(typeModel);
请注意,我们设置组合框映射的方法与设置其他窗口部件的方法相同,但我们对其应用了自己的模型,这样它就会显示自己模型typeModel
中的数据,而不是显示包含每个人数据的模型中的数据。
接下来,我们设置 widget 映射器,将每个输入 widget 与调用setModel() 时指定的模型中的一列相关联:
mapper = new QDataWidgetMapper(this); 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); 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("Delegate Widget Mapper")); mapper->toFirst(); }
模型在窗口的setupModel()
函数中初始化。在这里,我们创建了一个 5 行 3 列的标准模型。在每一行中,我们插入名称、地址和表示地址类型的值。地址类型存储在一个字符串列表模型中。
void Window::setupModel() { QStringList items; items << tr("Home") << tr("Work") << tr("Other"); typeModel = new QStringListModel(items, this); model = new QStandardItemModel(5, 3, this); QStringList names; names << "Alice" << "Bob" << "Carol" << "Donald" << "Emma"; QStringList addresses; addresses << "<qt>123 Main Street<br/>Market Town</qt>" << "<qt>PO Box 32<br/>Mail Handling Service" "<br/>Service City</qt>" << "<qt>The Lighthouse<br/>Remote Island</qt>" << "<qt>47338 Park Avenue<br/>Big City</qt>" << "<qt>Research Station<br/>Base Camp<br/>Big Mountain</qt>"; QStringList types; types << "0" << "1" << "2" << "0" << "2"; for (int row = 0; row < 5; ++row) { QStandardItem *item = new QStandardItem(names[row]); model->setItem(row, 0, item); item = new QStandardItem(addresses[row]); model->setItem(row, 1, item); item = new QStandardItem(types[row]); model->setItem(row, 2, item); } }
当我们将每一行插入模型时,就像数据库中的记录一样,我们会存储与typeModel
中每个人的地址类型对应的值。当部件映射器从每一行的最后一列读取这些值时,需要将它们用作typeModel
中值的引用,如下图所示。这就是委托的用途。
为了完整起见,我们展示了updateButtons()
插槽的实现:
void Window::updateButtons(int row) { previousButton->setEnabled(row > 0); nextButton->setEnabled(row < model->rowCount() - 1); }
总结和进一步阅读
为组合框使用单独的模型提供了一个与存储在主模型中的数据分开的选择菜单。使用命名映射将组合框的currentIndex
属性与模型中的列相关联,可以有效地在模型中存储查找值。
但是,当在部件映射器的上下文之外读取模型时,我们需要了解typeModel
才能理解这些查找值。如果能将typeModel
中的数据和选择存储在一个地方,那将会非常有用。SQL Widget Mapper 示例就涵盖了这一点。
© 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.