在我的应用程序中,我有一个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
。
感谢。
答案 0 :(得分:0)
您可以使用布尔值来阻止递归执行函数体。
更简单的解决方案是
QAbstractItemView::NoEditTriggers
,clicked
来打开/显示QDialog
而非代表,QDataWidgetMapper
的模型字段相关联。然后可以重复使用相同的QDialog
,然后使用QDataWidgetMapper::setCurrentIndex
填充控件,然后再显示exec()
以及QDataWidgetMapper::submit()
或revert()
用户验证或取消更改。
由于QDataWidgetMapper
和QTableView
将共享相同的模型,因此表格视图将自动更新。