Qt4中QTreeView无法显示已有模型新增内容的问题
你的问题核心在于Qt模型视图架构的信号通知机制——当你在load()里往现有模型添加数据时,没有触发模型的变更通知信号,导致QTreeView完全不知道数据已经更新;而load2()因为重新创建并绑定了模型,视图会重新初始化并加载所有数据,所以能正常显示。
要在不新建模型的前提下实现动态更新,你需要修改自定义模型QDataItemTree的实现,确保每次添加数据时都通知视图。
具体修改步骤
1. 给自定义模型的添加方法加上变更通知
Qt的QAbstractItemModel子类必须通过beginInsertRows()和endInsertRows()这对方法,在数据变更前后发出信号,视图才能感知到并刷新界面。假设你的QDataItemTree继承自QAbstractItemModel,请修改以下三个添加方法:
// 示例:修改addBatch方法 QDataItem* QDataItemTree::addBatch(int batchNum, QDataItem* parentItem) { if (!parentItem) { parentItem = rootItem; // 假设rootItem是你的根节点对象 } // 获取父节点对应的模型索引 QModelIndex parentIndex = createIndex(parentItem->row(), 0, parentItem); // 通知模型:要在父节点的末尾插入一行 beginInsertRows(parentIndex, parentItem->childCount(), parentItem->childCount()); // 实际添加数据的逻辑 QDataItem* batchItem = new QDataItem(QString("Batch %1").arg(batchNum), parentItem); parentItem->appendChild(batchItem); // 结束插入,自动发出rowsInserted信号 endInsertRows(); return batchItem; }
同理,addBatchElement和addBatchElementChild也要做完全相同的修改:在创建并添加子项之前调用beginInsertRows,添加完成后调用endInsertRows。
2. 移除load()中多余的模型绑定语句
你的load()函数最后一行ui->treeView->setModel(tree_view_model_);完全没必要,模型已经和视图绑定过了,重复设置反而可能导致不必要的视图重置。直接删掉这行代码。
3. 确保QDataItem类的辅助方法正确实现
你的QDataItem类需要提供以下两个方法,供模型获取节点的位置和子项数量:
class QDataItem { // ... 其他成员 public: // 返回当前节点在父节点中的行号 int row() const { if (parentItem_) { return parentItem_->children_.indexOf(const_cast<QDataItem*>(this)); } return 0; } // 返回当前节点的子项数量 int childCount() const { return children_.size(); } private: QList<QDataItem*> children_; QDataItem* parentItem_; };
为什么这样有效?
Qt的模型视图架构是信号驱动的:视图只会在模型发出rowsInserted、dataChanged等信号时,才会主动去查询新数据并更新界面。直接修改模型的内部数据而不发信号,视图根本不知道数据发生了变化,自然不会刷新。
beginInsertRows()和endInsertRows()不仅会帮你发出正确的信号,还会在插入过程中锁定模型状态,避免视图在数据更新时访问到不一致的内容。
内容的提问来源于stack exchange,提问作者apalomer

