首页 > 解决方案 > 为不断变化但只读的模型子类化 QAbstractListModel 的正确方法是什么?

问题描述

我已经阅读并尝试了各种东西,主要是这里列出的那些http://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html

所以基本上我有一些 C++ 类,其中包含一个具有一些属性的事物列表。这个事情列表的变化基本上超出了我的控制(硬件/网络节点出现和离开)并发出它改变的信号。

我一直在做的测试是公开一个带有QStringList属性的 C++ 类型。这可以正常工作,但不允许公开多个属性,并且它还会为每次更新重置视图。

C++

Q_PROPERTY(QStringList robots READ robots NOTIFY robotsChanged)

QStringList StatusInfo::robots() {
    auto samples = statusReader.read();
    QStringList dataList;
    for (auto& sample: samples) {
        std::string id = sample->data().id();
        dataList.append(QString::fromStdString(id));
    }
    return dataList;
}

void StatusInfo::on_data_available( dds::sub::DataReader<Operator::StatusInformation>& dr) {
    emit robotsChanged();
}

QML:

    ListView {
      id: robotList
      model: status.robots
      delegate: RobotItem {}
    }

另一种选择是 subclassing QAbstractListModel,这似乎是制作更复杂模型的“正确”方式。除了不清楚我需要覆盖哪些方法以及要发出哪些信号。

子类化部分:

在继承 QAbstractListModel 时,您必须提供 rowCount() 和 data() 函数的实现。表现良好的模型还提供了 headerData() 实现。

好了,就这么清楚了。每个模型都需要这个。

对于可编辑列表模型,您还必须提供 setData() 的实现,并实现 flags() 函数,以便它返回一个包含 Qt::ItemIsEditable 的值。

我的模型不可编辑,所以不能。

为可调整大小的类列表数据结构提供接口的模型可以提供 insertRows() 和 removeRows() 的实现。在实现这些函数时,调用适当的函数很重要,这样所有连接的视图都知道任何变化。

这就是棘手的地方。我不想为可调整大小的类似列表的数据结构提供接口。但是我的模型的长度改变。

更复杂的是,上面DataReader只是返回一个项目列表,而不是一些很好的插入命令,所以没有简单的方法来调用beginInsertRows和朋友。

正确的方法是什么?

标签: c++qtqml

解决方案


推荐阅读