使用新数据更新QTreeView不正确

时间:2022-11-03 15:04:22

Starting from the popular Qt SimpleTreeModel, I want to be able to update the entire tree view with new data. The example only populates the tree view once on start up, it does not update the tree view afterwards.

从流行的Qt SimpleTreeModel开始,我希望能够使用新数据更新整个树视图。该示例仅在启动时填充树视图,之后不会更新树视图。

I have made some edits to the example (treeview is now in a dialog so I can press "PushButton" to update treeview) and when I update the tree view, the top most TreeItems become the child TreeItems for each topmost TreeItem. When I update the treeview in this case, before and after should be the same as it is the same data, I don't see why before and after would be different. The screenshots below better illustrate the problem:

我已对该示例进行了一些编辑(treeview现在在对话框中,因此我可以按“PushButton”来更新树视图),当我更新树视图时,最顶层的TreeItems成为每个最顶层TreeItem的子TreeItems。当我在这种情况下更新树视图时,之前和之后应该是相同的数据相同,我不明白为什么之前和之后会有所不同。下面的屏幕截图更好地说明了问题:

Before Updating

使用新数据更新QTreeView不正确

After Updating, you can see below that if I click on a item that is used multiple times, they all highlight, which makes sense as they are all (probably) pointing to the same item (I'm not sure how).

更新后,你可以看到如果我点击一个多次使用的项目,它们都会突出显示,这是有意义的,因为它们都(可能)指向同一个项目(我不知道如何)。

使用新数据更新QTreeView不正确

My edits to the SimpleTreeModel are below:

我对SimpleTreeModel的编辑如下:

main.cpp

#include "dialog.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    Q_INIT_RESOURCE(simpletreemodel);

    QApplication app(argc, argv);

    Dialog dialog;
    dialog.show();

    return app.exec();
}

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

#include <QFile>

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);

    QFile file(":/default.txt");
    file.open(QIODevice::ReadOnly);
    model = new TreeModel(file.readAll());
    file.close();

    ui->treeView->setModel(model);
}

Dialog::~Dialog()
{
    delete ui;
}

void Dialog::on_pushButton_clicked()
{
    model->redrawAll();
}

treeitem.cpp (exactly the same as example except with new function below)

treeitem.cpp(与示例完全相同,但下面有新功能)

void TreeItem::removeChildren() {
    m_childItems.clear();
}

treemodel.cpp (exactly the same as example except with new functions below). I am removing all children from rootItem so I can put completely new data on a each update.

treemodel.cpp(与示例完全相同,除了下面的新函数)。我将从rootItem中删除所有子项,以便我可以在每次更新时放入全新的数据。

TreeModel::TreeModel(const QString &data, QObject *parent)
    : QAbstractItemModel(parent)
{
    QList<QVariant> rootData;
    this->data1 = data;
    rootData << "Title" << "Summary";
    rootItem = new TreeItem(rootData);
    setupModelData(data.split(QString("\n")), rootItem);
}

void TreeModel::redrawAll() {
    rootItem->removeChildren();

    setupModelData(data1.split(QString("\n")), rootItem);

    emit dataChanged(QModelIndex(), QModelIndex());

}

EDIT: I have modified the redrawAll function to below. The result is the same screenshot after updating as the previous TreeModel::redrawAll() function with emit dataChanged(QModelIndex(), QModelIndex()).

编辑:我已将redrawAll函数修改为下面。更新后的结果与之前使用emit dataChanged(QModelIndex(),QModelIndex())的TreeModel :: redrawAll()函数相同。

void TreeModel::redrawAll() {
//    beginResetModel();
    rootItem->removeChildren();

    QFile file(":/default.txt");
    file.open(QIODevice::ReadOnly);
    QString data = file.readAll();
    setupModelData(data.split(QString("\n")), rootItem);
    file.close();

//    endResetModel();

//    emit dataChanged(QModelIndex(), QModelIndex());

    qDebug() << "TreeModel::redrawAll() " << rowCount() << columnCount();
// the output is TreeModel::redrawAll()  6 2
    QModelIndex topLeft = this->index(0, 0);
    QModelIndex bottomRight   = this->index(rowCount(), columnCount());
    emit dataChanged(topLeft, bottomRight);

}

1 个解决方案

#1


0  

The dataChanged() signal that you emit is nonsense. Not only is the invalid index range not allowed, but dataChanged() only indicates a change in contents of the data items, not in the structure of the tree. You seem to be changing the structure as well.

您发出的dataChanged()信号是无意义的。不仅无法使用无效索引范围,而且dataChanged()仅指示数据项内容的更改,而不是树结构中的更改。你似乎也在改变结构。

Since you seem to be changing the contents the entire model, you should indicate that you've reset the model:

由于您似乎正在更改整个模型的内容,因此您应该指示您已重置模型:

void TreeModel::redrawAll() {
  beginResetModel();
  ...
  endResetModel();
}

#1


0  

The dataChanged() signal that you emit is nonsense. Not only is the invalid index range not allowed, but dataChanged() only indicates a change in contents of the data items, not in the structure of the tree. You seem to be changing the structure as well.

您发出的dataChanged()信号是无意义的。不仅无法使用无效索引范围,而且dataChanged()仅指示数据项内容的更改,而不是树结构中的更改。你似乎也在改变结构。

Since you seem to be changing the contents the entire model, you should indicate that you've reset the model:

由于您似乎正在更改整个模型的内容,因此您应该指示您已重置模型:

void TreeModel::redrawAll() {
  beginResetModel();
  ...
  endResetModel();
}