2016-10-11 216 views
0

我写了一个派生自QAbstractModelItem的类。它在QTreeView上使用。令人遗憾的是,官方文档示例并未显示如何添加或删除模型上的项目。我认为这很容易做到,所以我闯入了它。问题是删除选定的对象会导致异常。例如:QTreeView/QAbstractItemModel - 删除导致异常

用户单击QTreeView上的一行,并希望将其与其所有子项(如果有)一起删除。这是一个被执行的代码:

MyModel.cpp: 

// This gets called with the QModelIndex of the currently selected row. 
void MyModel::remove(const QModelIndex &index) { 
    if (!index.isValid()) 
     return; 
    MyItem * selectedItem = static_cast<MyItem*>(index.internalPointer()); 
    beginRemoveRows(index, index.row(), index.row()); 
    // Call the method on the selected row object that will delete itself and all its children: 
    selectedItem->destroy(); 
    endRemoveRows(); 
} 

MyItem.h: 

// A pointer list with child items. 
std::vector<MyItem*> children; 

MyItem.cpp: 

// Deletes all children of this object and itself. 
void MyItem::destroy(bool isFirst) { 
    if (children.size() > 0) { 
     // Each child needs to run this function, to ensure that all nested objects are properly deleted: 
     for each (auto child in children) 
      child->destroy(false); 
     // Now that the children have been deleted from heap memory clear the child pointer list: 
     children.clear(); 
    } 
    // This boolean determines wether this object is the selected row/highest object in the row hierachy. Remove this object from the parent's pointer list: 
    if(isFirst) 
     parent->removeChild(this); 
    // And lastly delete this instance: 
    if(!isFirst) // This will cause a memory leak, but it is necessary 
     delete this; // <- because this throws an exception if I run this on the first object. 
} 

// Removes a single child reference from this instance's pointer list. 
void MyItem::removeChild(MyItem * child) 
{ 
    auto it = std::find(children.begin(), children.end(), child); 
    children.erase(it); 
} 

现在,如果我们不介意小的内存泄漏这工作得很好。 ^^

但是,如果我尝试的第一个/所选行对象运行delete命令 - 那么两个例外之一发生:

  1. 该行有孩子: 抛出异常:读访问冲突。这是0xDDDDDDDD。
  2. 该行没有子女: 抛出异常:写入访问冲突。 _Parent_proxy是0x64F30630。

我保持代码简短但希望它包含我的错误。或者有人知道一个很好的QTreeView/QAbstractItemModel示例,它显示了如何添加/删除项目?

亲切的问候 空

+1

首先,我认为你必须使用在beginRemoveRows父指数调用:beginRemoveRows(index.parent(),index.row(),index.row( )) – Fabio

+0

非常感谢! :)这是异常的原因,现在它工作。如果您重新发布您的答案,我会将其标记为已解决。 – Sora

回答

0

我认为这是在MyModel::remove方法错误。 beginRemoveRows作为父索引的第一个参数,而不是索引本身。宥需要更换这一行:

beginRemoveRows(index.parent(), index.row(), index.row());