子模型/视图用于定制对象列表的模型

Sam*_*Sam 3 c++ model-view-controller qt qt4

我对Qt的经验不足,无法做出好的设计选择。经验丰富的Qt程序员的任何帮助将不胜感激。
我正在尝试找出要子类化的模型,要使用的视图,应该执行的委托子类化/扩展...

我的问题类似于:我要显示这些区域,每行1个:

class Zone{

    //inputs
    string country;  //edited with a QComboBox
    string city;     //edited with a QComboBox
    int ageMin;

    //stored result
    int nbInhabitantsOlderThanMin;
}
Run Code Online (Sandbox Code Playgroud)

这是我想要做的,每个需求的设计选择使我想到:

  • 我想显示它们的列表(-> QListView
  • 但是要显示一项,我需要几列(-> QTableView
  • 我想要双击以触发自定义窗口小部件中的编辑,因为无法编辑nbInhabitantsOlderThanMin,并且选择国家/地区限制了可以在QComboBox中选择的城市列表(反之亦然) ->我可能应该在某个地方使用QDataWidgetMapper(或子类?)。

    因此,尽管行的版本应该在小部件中进行,但显示是简单的/不是自定义的,并且将委托子类化(例如,QStyledItemDelegate)(我不太确定这一点)似乎不是正确的方法具有1个自定义窗口小部件以及许多子输入窗口小部件,以同时编辑3个字段。
    我认为要建模的数据将偏向于QAbstractListModel的模型子类,但是具有许多与默认委托查看兼容的列的显示偏向于QAbstractTableModel

所以我真的不知道该选择哪种设计。任何有经验的帮助连接点都是非常欢迎的:)

Liz*_*Liz 5

QDataWidgetMapper有点不同。这是一种使用自定义控件显示模型(例如QStandardItemModel)中的一项的方法。您可以在此处阅读更多有关它的信息,并附带快照和如何实现快照的示例。

虽然肯定很酷,但我认为这不是您想要的。主要是因为您指定要以列表格式查看项目。但是,您可以在一个简单的列表中显示所有项目,双击即可使用QDataWidgetMapper打开一个对话框。在这种情况下,您需要使用QListView / QListWidget来实现双击事件。

不过,我个人不喜欢额外的窗口给用户增加的负担。我更喜欢少量使用弹出窗口。但是,如果您喜欢这种方法,那就继续吧。 是QDataWidgetMapper的另一个示例,非常好。

我的首选方法仍然是使用QTableView,并为需要专门编辑的列提供委托。 是有关模型/视图的所有内容的出色演练。因此,如果您决定使用QListView或QTableView,它将为您提供一个良好的开端。它还讨论了如何创建委托以编辑所需字段。

那么,如何创建自定义委托?基本上,您只是从QItemDelegate继承。上面的链接中有一些示例,但我将重点介绍几个要点。

QWidget *ComboBoxDelegate::createEditor(QWidget *parent,
     const QStyleOptionViewItem &/* option */,
     const QModelIndex &index) const
 {
     QComboBox *editor = new QComboBox (parent);
     //  Add items to the combobox here.
     //  You can use the QModelIndex passed above to access the model
     //  Add find out what country was selected, and therefore what cities
     //  need to be listed in the combobox

     return editor;
 }

void ComboBoxDelegate::setEditorData(QWidget *editor,
                                     const QModelIndex &index) const
 {
     int value = index.model()->data(index, Qt::EditRole).toInt();

     QComboBox  *comboBox= static_cast<QComboBox *>(editor);
     int _SelectedItem = // Figure out which is the currently selected index;
     comboBox->setCurrentIndex(_SelectedItem);
 }

void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                    const QModelIndex &index) const
 {
     QComboBox  *comboBox= static_cast<QComboBox *>(editor);
     comboBox->interpretText();
     int value = comboBox->currentIndex();
     //  Translate the current index to whatever you actually want to
     // set in your model.

     model->setData(index, value, Qt::EditRole);
}
Run Code Online (Sandbox Code Playgroud)

填补我在示例中留下的空白,您就有了代表。现在,如何在您的QTableView中使用它:

您可以为表的特定列设置委托,如下所示:

setItemDelegateForColumn(_ColumnIndex, new ComboBoxDelegate(_YourTableModel));
Run Code Online (Sandbox Code Playgroud)

并且,如果您想防止某些列可编辑:

_YourTableModel->setColumnEditable(_ColumnIndex, false);
Run Code Online (Sandbox Code Playgroud)

设置好模型后,其他所有事情都应该照顾好自己。

希望能有所帮助。