无法在 QAbstractItemModel 的 dataChanged 信号槽中获取发送者对象

Posted

技术标签:

【中文标题】无法在 QAbstractItemModel 的 dataChanged 信号槽中获取发送者对象【英文标题】:Unable to obtain sender object in slot of dataChanged signal of QAbstractItemModel 【发布时间】:2016-11-22 16:34:34 【问题描述】:

我对 QAbstractItemModel 进行了子类化,并尝试在 dataChanged 信号槽中检索小部件。

connect(model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(slotDataChanged(const QModelIndex&, const QModelIndex&)));

void MyEditor::slotDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight)

    QComboBox* widget = dynamic_cast<QComboBox*>(sender());
    if (widget)
    
         // do something
    

这里我每次都得到一个空小部件,与 qobject_cast 的结果相同。

我在我的表格视图中设置组合框小部件,这是一个派生 QStyledItemDelegate 的委托类。

MyDelegate* myDelegate;
myDelegate = new MyDelegate();
tableView->setItemDelegate(myDelegate);
tableView->setModel(model);


 QWidget* MyDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
 
      QComboBox* cb = new QComboBox(parent);
      cb->addItem(QString("All"));
      cb->setCurrentIndex(0);
      return cb;
 

在这种情况下如何获取 sender 对象?谢谢。

【问题讨论】:

dataChanged() 从模型中发出(因为它是QAbstractItemModel 的信号之一)。它不是发出了编辑器小部件。是什么让你认为它会从那里发出?您只能将 sender() 转换为 QAbstractItemModel 您还应该在QObject 上使用qobject_cast,而不是dynamic_cast:它会更快,并且在没有RTTI 的情况下也可以工作。 无论如何使用 qobject_cast 来解析 QObject 派生的指针。 你能更广泛地展示你想要实现的目标吗?为什么在模型中的数据已经更新后还需要访问编辑器小部件? @Mike 是的,我知道 dataChanged() 信号是从模型中发出的。每当我的模型中的某些数据发生更改以通知视图时,我都会明确地发出它。我观察到,每当我在编辑器中双击任何单元格时,都会发出相同的信号,我试图通过获取用户双击的小部件来处理它的插槽中的一些事情。反正我已经实现了。谢谢。 【参考方案1】:

不知道你的意图是什么。当模型中的数据已经更新时获取编辑器小部件通常是不必要的。 在我看来,解决您的问题需要对Model-View-Delegate概念的简要介绍。

简而言之,在您的情况下为QTableView 的视图本身没有数据。 View 通过调用data 方法从附加模型中获取数据。当用户尝试编辑某些数据时,会调用委托 createEditorsetEditorData 方法。后者将模型指针作为参数之一,因此它可以访问需要表示的实际数据。

当用户完成编辑时,setModelData 被调用,它具有可用于获取更新值的编辑器小部件。它还具有可用于更改通常通过setData 方法完成的正确数据输入的模型。此时会发出 dataChanged 信号,通知视图相应的数据已更新,以便刷新显示的值。

因此,请尝试重新考虑您的设计。也许您想要实现的目标可以采用不同的方式实现,或者您的实现可以稍作修改以符合所描述的流程。

您还可以查看 Qt 站点以获取 Star Delegate Example 以查看一些示例实现,或查看 Model View Tutorial 以获取有关模型视图主题的更广泛描述。

【讨论】:

感谢您为我指明正确的方向。我的模型/视图设计很好,我只是从上面提到的教程中学到的。这是一个相当简单的问题,现在我已经解决了。你能帮我解决这个问题吗,我在这个问题上挣扎了很长时间:***.com/questions/40724282/…【参考方案2】:

我的模型/视图设计很好。当用户在我的编辑器中双击一个单元格时,我只需要获取一个小部件。

QComboBox* widget = dynamic_cast<QComboBox*>(tableView->indexWidget(topLeft));
if (widget)

    // Do something

在 slotDataChanged 中,我使用 QModelIndex 获得了所需的小部件。 感谢您帮助我。

【讨论】:

以上是关于无法在 QAbstractItemModel 的 dataChanged 信号槽中获取发送者对象的主要内容,如果未能解决你的问题,请参考以下文章

Qt QAbstractItemModel 重新排列图像

QAbstractItemModel::columnCount - 每行的可变列数

QAbstractItemModel - QModelIndex 对象在创建时是不是应该被缓存?

在 QAbstractItemModel 中不区分大小写排序

如何在 QAbstractItemModel 中为 QTreeView 创建人工节点

Qt:QAbstractItemModel 中的 setData 方法