我将QAbstractItemModel
子类化为显示QTreeView
中的项目,并且在此子类(projectModel
)中,我有一个函数来删除树视图中当前选择的索引。 Component
是用于表示模型的所有成员的类:
void
projectModel::deleteComponent()
{
QModelIndex child_index = _treeview->selectionModel()->currentIndex();
Component* child = static_cast<Component*>(child_index.internalPointer());
Component* parent = child->Parent();
QModelIndex parent_index = createIndex(parent->row(), 0, parent);
int row = child->row();
beginRemoveRows(parent_index, row, row);
parent->delete_child(child);
endRemoveRows();
}
在致电beginRemoveRows
之前,父母和孩子的指示和原始指针都很好;调试器显示它们指向正确的项目及其父项。但是,在调用beginRemoveRows
后程序崩溃了。具体来说,它在projectModel::parent()
:
QModelIndex
projectModel::parent(const QModelIndex &index) const
{
if (!index.isValid())
return QModelIndex();
Component* item = getItem(index); //Fails to cast index internal pointer to a valid Component*
Component* parentItem = item->Parent();
if (parentItem == _rootnode)
return QModelIndex();
return createIndex(parentItem->row(), 0, parentItem);
}
当我打破崩溃并检查调试器输出时,它显示item
函数中的变量parent()
是垃圾。不知何故,我的QModelIndex
在deleteComponent
的调用和parent
的调用之间被破坏了。我正在做的事情有什么明显的错误,或者问题可能更微妙?
答案 0 :(得分:8)
这是完全可以预期的。
在您更改模型的结构之前,非持久性索引有效。结构更改是指发出其他而不是发出dataChanged
的任何更改。
结构变化必须被视为索引生命周期的障碍:您必须丢弃在结构更改之前保留的任何非持久性索引。
根据调用deleteComponent
的位置,可能会发生的情况是调用者持有一些索引,deleteComponent
使所有索引无效,并且您从此处开始处于未定义的行为区域。< / p>
如果您希望持久性索引在结构更改中保持有效,则需要使用持久性索引,即使这样,只有在给定项目仍然存在的情况下它们才有效。如果您正在使用自己的模型,则需要明确支持持久性索引,并且模型的用户必须使用它们。