使用代理一次编辑多个数据项

时间:2012-02-14 21:43:38

标签: c++ qt

在我的应用程序中,我有一个QSqlTableModel填充了一个来自MySQL连接的表。为了显示其内容,我使用QTableView;为了编辑和显示它,我将QStyledItemDelegate。{/ p>分组

我需要能够编辑整个模型行。为了实现这一点,我使用QModelIndex::sibling方法来检索/设置该行中的所有值,而不管哪个(行/列)对“激活”了委托。

有了这个,我可以构建一个QDialog子类(我的委托编辑器)并用所选行的当前值填充它。然后让用户编辑内容,然后提交更改或丢弃它们,具体取决于用户是否单击“保存”或“取消”。

问题是:我使用QAbstractItemModel::setData将更改保存回模型中。但在某些条件下(仍然未知),此方法会调用QAbstractItemDelegate::setEditorData,它会覆盖当前存在于模型中的旧内容的QDialog子类中的新内容。

当发生这种情况时,对QAbstractItemModel::setData的任何下一次调用都会写入模型中包含的内容,而不是用户选择的新值,因为先前对QAbstractItemDelegate::setEditorData的调用使{ {1}}子类从与发起问题的QDialog对应的列中丢失用户选择的所有信息。

有谁知道如何防止此问题发生?

部分代码:

QAbstractItemModel::setData

带有“HERE”注释的行导致了问题(根据调试)。

编辑(新信息): 我只是意识到在保存导致“编辑”的列之后总是调用QWidget *MedicationDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/) const { EditMedicationDialog *editor = new EditMedicationDialog(parent); editor->setAttribute(Qt::WA_DeleteOnClose, true); editor->setModal(true); connect(editor, SIGNAL(accepted()), this, SLOT(editorAccepted())); connect(editor, SIGNAL(rejected()), this, SLOT(editorRejected())); return editor; } void MedicationDelegate::setEditorData(QWidget *uncastedEditor, const QModelIndex& index) const { int currentRow = index.row(); QModelIndex drugClassIndex = index.sibling(currentRow, MedicationModel::DrugClass); QModelIndex drugIndex = index.sibling(currentRow, MedicationModel::Drug); QModelIndex dosageIndex = index.sibling(currentRow, MedicationModel::Dosage); QModelIndex amountIndex = index.sibling(currentRow, MedicationModel::Amount); QModelIndex scheduleIndex = index.sibling(currentRow, MedicationModel::Schedule); QModelIndex frequencyIndex = index.sibling(currentRow, MedicationModel::Frequency); QString drugClass = index.model()->data(drugClassIndex, Qt::DisplayRole).toString(); QString drug = index.model()->data(drugIndex, Qt::DisplayRole).toString(); QString dosage = index.model()->data(dosageIndex, Qt::DisplayRole).toString(); QString amount = index.model()->data(amountIndex, Qt::DisplayRole).toString(); QString schedule = index.model()->data(scheduleIndex, Qt::DisplayRole).toString(); QString frequency = index.model()->data(frequencyIndex, Qt::DisplayRole).toString(); EditMedicationDialog *editor = qobject_cast<EditMedicationDialog*>(uncastedEditor); // these methods sets the current row values in the editor editor->setDrugClass(drugClass); editor->setDrug(drug); editor->setDosage(dosage); editor->setAmount(amount); editor->setSchedule(schedule); editor->setFrequency(frequency); } void MedicationDelegate::setModelData(QWidget *uncastedEditor, QAbstractItemModel *model, const QModelIndex& index) const { int currentRow = index.row(); QModelIndex drugClassIndex = index.sibling(currentRow, MedicationModel::DrugClass); QModelIndex drugIndex = index.sibling(currentRow, MedicationModel::Drug); QModelIndex dosageIndex = index.sibling(currentRow, MedicationModel::Dosage); QModelIndex amountIndex = index.sibling(currentRow, MedicationModel::Amount); QModelIndex scheduleIndex = index.sibling(currentRow, MedicationModel::Schedule); QModelIndex frequencyIndex = index.sibling(currentRow, MedicationModel::Frequency); EditMedicationDialog *editor = qobject_cast<EditMedicationDialog*>(uncastedEditor); model->setData(drugClassIndex, editor->drugClass()); model->setData(drugIndex, editor->drug()); // HERE model->setData(dosageIndex, editor->dosage()); model->setData(amountIndex, editor->amount()); model->setData(scheduleIndex, editor->schedule()); model->setData(frequencyIndex, editor->frequency()); } 。我总是在“药物”栏中点击两次。因此,在该版本之后调用QAbstractItemModel::setData

感谢。

1 个答案:

答案 0 :(得分:0)

您可以使用布尔值来阻止递归执行函数体。

更简单的解决方案是

  • 通过将编辑触发器设置为QAbstractItemView::NoEditTriggers
  • 使模型为只读
  • 例如,使用视图的信号clicked来打开/显示QDialog而非代表,
  • 并将对话框内的控件与带有QDataWidgetMapper的模型字段相关联。

然后可以重复使用相同的QDialog,然后使用QDataWidgetMapper::setCurrentIndex填充控件,然后再显示exec()以及QDataWidgetMapper::submit()revert()用户验证或取消更改。

由于QDataWidgetMapperQTableView将共享相同的模型,因此表格视图将自动更新。