我可以在public Git repository on BitBucket上找到与此问题相关的源代码。
我正在尝试使用mainwindow.cpp中的以下代码动态地将一些项添加到QTreeView模型中:
if(dlg->exec() == QDialog::Accepted) {
QList<QVariant> qList;
qList << item.name << "1111 0000" << "0x00";
HidDescriptorTreeItem *item1 = new HidDescriptorTreeItem(qList, hidDescriptorTreeModel->root());
hidDescriptorTreeModel->root()->appendChild(item1);
}
这在我的MainWindow构造函数中运行时,就在 ui->setupUi(this) 之后,但我需要在事件过滤器中运行,但相同的代码无法获得QTreeView更新。当我在mainwindow.cpp:70设置断点并逐步执行接下来的几行时,我可以看到数据正被添加到模型中,但我需要刷新QTreeView。
我理解这是通过发出dataChanged()完成的,但不确定如何做到这一点。 dataChanged信号的信号签名如下:
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>());
所以我需要提出topLeft和bottomRight QModelIndex实例。如何从上面代码段中的 item1 构建/获取这些内容?
此外,beginInsertRows()和endInsertRows()在哪里进入视图,我应该调用这些函数吗?
答案 0 :(得分:3)
来自QAbstractItemModel文档:
void QAbstractItemModel::beginInsertRows ( const QModelIndex & parent, int first, int last ) [protected]
Begins a row insertion operation.
When reimplementing insertRows() in a subclass, you must call this function before inserting data into the model's underlying data store.
The parent index corresponds to the parent into which the new rows are inserted; first and last are the row numbers that the new rows will have after they have been inserted.
其他受保护的功能也说类似的事情。
insertRows()说:
如果您实施自己的模型,则可以重新实现此功能 你想支持插入。或者,您可以提供 自己的API用于更改数据。 在任何一种情况下,您都需要致电 beginInsertRows()和endInsertRows()通知其他组件 模特已经改变了。
查看QAbstractItemModel protected functions和signals
视图连接到这些信号,以了解模型数据何时更改并重新排列内部数据。这些函数在内部发出信号,以便您在视图发生时轻松发出警告。但信号只能由抽象类发出。
连接到此信号的组件使用它来适应变化 模型的尺寸。它只能由QAbstractItemModel发出 实现,并且不能在子类代码中显式发出。
所以你必须坚持使用这些方法。
编辑以回答您的评论:
确实,Items应该引用模型并告诉它有关更改,检查来自QStandardItem的这些行:
void QStandardItem::emitDataChanged()
void QStandardItem::removeRows(int row, int count)
(注意,第二,它如何调用模型的rowsAboutToBeRemoved()和rowsRemoved())
也许您应该尝试使用QStandardItem和QStandardItemModel。 直接或子类化。它会隐藏很多丑陋的东西。
答案 1 :(得分:0)
这也是一种不太恰当但更简单的方法 - emit layoutChanged()
而不是dataChanged()
。更多信息 - https://stackoverflow.com/a/41536459/635693