qt5代理模型在主模型更新完成之前过早更新

时间:2014-05-05 14:46:49

标签: qt5

我有一个主模型(QStandardModel)的设置,一个更改DisplayRole输出的代理模型,以及一个显示每个模型的单独的tableview。在主模型数据中是一个用户角色,它存储指向另一个QObject的指针,代理模型使用该QObject来获得所需的显示值。

当删除该变量指向的对象时,我遇到了问题。我正在通过销毁(QObject *)信号处理主模型中的删除。在插槽内,我搜索模型,查找指向对象的任何项目并删除引用。

该部分本身工作正常,但我也连接到代理模型的onDataChanged(...)信号,我在代理模型上调用resizeColumnsToContents()。然后调用代理的data()函数。在这里,我检查项目是否有指针,如果有,则从对象中获取一些信息以供显示。

所有这一切的结果变成:

  1. 将要删除的对象触发销毁(...)信号
  2. 主模型使用已删除的对象查找任何项目,并调用setData以删除引用
  3. Tableview捕获代理模型的onDataChanged信号并调整列的大小
  4. 调用代理模型的数据(...)。它检查主模型中的项是否具有对象指针,如果是,则显示对象中的值。如果没有,它会显示其他内容。
  5. 问题是,在步骤4中,主模型中的项目显然仍未被删除;指针地址仍然存储。但是,指针引用的对象已被此点删除,从而导致段错误。

    如何在代理模型尝试更新之前修复我的设置以确保主模型完成删除指针引用?

    此外,这里是相关部分的伪代码:

    // elsewhere
    Object *someObject = new QObject();
    QModelIndex index = mainModel->index(0,0);
    mainModel->setData(index, someObject, ObjectPtrRole);
    // do stuff
    delete someObject; // Qt is actually doing this, I'm not doing it explicitly
    
    // MainModel
    void MainModel::onObjectDestroyed(QObject *obj)
    {
      // iterating over all model items
        // if item has pointer to obj
          item->setData(QVariant::fromValue(NULL), ObjectPtrRole));
    }
    
    // receives onDataChanged signal
    void onProxyModelDataChanged(...)
    {
      ui->tblProxyView->reseizeColumnsToContents();
    }
    
    void ProxyModel::data(const QModelIndex &index, int role) const
    {
      QModelIndex srcIndex = mapToSource(index);
      if(role == Qt::DisplayRole)
      {
        QVariant v = sourceModel()->data(srcIndex, ObjectPtrRole);
        Object *ptr = qvariant_cast<Object*>(v);
        if(ptr != NULL)
          return ptr->getDisplayData();
        else
          return sourceModel->data(srcIndex, role);
      }
    }
    

    问题是ptr不是NULL,但是在调用ProxyModel :: data(...)时删除了引用的对象,所以我最终得到了段错误。

1 个答案:

答案 0 :(得分:1)

为避免与QObject的实例悬挂指针解引用,您可以执行以下两项操作之一:

  1. 使用object->deleteLater - 一旦控件返回到事件循环,该对象将被删除。此类功能也称为autorelease pools

  2. 使用QPointer。删除对象后,它会将自身设置为null,因此您可以在使用前进行检查。