【问题标题】:Updating QTreeView with new data not correct用新数据更新 QTreeView 不正确
【发布时间】:2017-09-27 07:52:00
【问题描述】:

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

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

更新前

更新后,您可以在下面看到,如果我单击多次使用的项目,它们都会突出显示,这是有道理的,因为它们都(可能)指向同一个项目(我不确定如何) .

我对 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();
}

对话框.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(与example完全相同,但下面有新功能)

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

treemodel.cpp(与example 完全相同,除了下面的新功能)。我正在从 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());

}

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

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);

}

【问题讨论】:

    标签: c++ qt treeview qtreeview


    【解决方案1】:

    您发出的dataChanged() 信号是无稽之谈。不仅不允许无效的索引范围,而且dataChanged() 仅表示数据项的内容发生了变化,而不是树的结构。你似乎也在改变结构。

    由于您似乎要更改整个模型的内容,因此您应该表明您已重置模型:

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

    【讨论】:

    • 我已经尝试了你的建议并且它有效(之前和之后是相同的),但是它关闭了树视图的所有分支。在我的实际项目中,我每秒更新多次,因此在更新后扩展每一行是不切实际的。在这个问题中,每次更新的结构都是相同的,只是内容在变化(在我的帖子中,每次更新的数据应该相同)。 dataChanged 的​​范围来自这里(我在 qt 文档中没有找到任何关于此的内容)stackoverflow.com/questions/29141038/…
    • 如果你保持模型的结构相同,那么你需要为树的每个不是叶子的分支发出dataChanged信号,并且每个信号都应该覆盖其中的所有子节点分支。这两个无效索引不起作用 - 你已经知道了。
    • 我用新的TreeModel::redrawAll() 函数编辑了我的问题。但是emit dataChanged(topLeft, bottomRight) 给出的结果与emit dataChanged(QModelIndex(), QModelIndex()) 相同。实际上,每个 topLeft、bottomRight 组合都会给出相同的结果,例如[ (0,0), (1,1) ]; [ (0,0), (0,0) ]; [ (1,1), (1,1) ]; [ (0,0), (6,2) ];(除了 [ (0,0), (0,0) ]; [ (1,1), (1,1) ]; 比其他更新需要更长的时间?)我不确定我是什么我做错了吗?
    猜你喜欢
    • 1970-01-01
    • 2014-01-09
    • 2014-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-15
    • 1970-01-01
    相关资源
    最近更新 更多