【问题标题】:List model inherited from QAbstractListModel, list item properties won't update from QML从 QAbstractListModel 继承的列表模型,列表项属性不会从 QML 更新
【发布时间】:2023-12-30 19:56:01
【问题描述】:

我很难解释我的问题,所以我只想让它变得简单,并希望它能完成工作。我正在使用 Qt5 和 QtQuick 2.0。

我创建了一个继承自 QAbstractListModel 的 MyListModel 类,并保存 MyListItem 类型的项目。我在 QML ListView 中将它用作 model: myListModel,并且委托在一个可爱的 TextInput 框中显示来自 MyListItem 的 quantity 属性。一切正常。

但是,当我从委托更改 quantity 值时,模型中的项目不会更新。我知道它们没有更新,因为我的 setQuantity(long desired_quantity) 函数(MyListItem 的成员)没有运行。长话短说,我不知道如何从委托中实际调用 setQuantity 函数。我可以手动将Q_PROPERTY(long quantity READ quantity WRITE setQuantity) 添加到MyListItem,然后使用setContextProperty()MyListItem myTemp 对象公开给QML,然后调用myTemp.quantity = 10。但很明显,如果委托不能写入数量属性(它只能从中读取),它就没有做这项工作。

有人能指出我正确的方向吗?我觉得我已经尝试了 Qt 设计师可能期望的一切,但我什么也没得到。而且我找不到任何可以明确解决我的问题的文档。

【问题讨论】:

    标签: qml qt-quick qt5


    【解决方案1】:

    TextInput 框不会自动更新您的 c++ 模型,您必须自己执行此操作。您可以通过向模型添加插槽或 Q_INVOKABLE 方法来做到这一点:

    //add a slot to you model
    public slots:
     setDataInModel(const int index, const QVariant &value);
    //or add Q_INVOKABLE method:
    public:
     Q_INVOKABLE setData(const int index, const QVariant &value);
    

    您必须实现其中一种方法,以便它更改模型中的相应数据行。更新后不要忘记在方法内部调用 dataChanged 方法。然后,当 TextInput 更新时,您必须从 QML 委托手动调用这些方法:

    onAccepted: {
      model.setDataInModel(index, text)
    }
    

    这里 index 是在每个委托中定义的属性,而 text 是来自 TextInput 的文本。

    【讨论】:

    • 那行得通。您是否有任何关于为什么委托不简单地预先制作对列表对象的引用而不仅仅是索引的问题?因为为了让 QSortFilterProxyModel 对象在我正在使用的模型上运行,我必须继承 QSortFilterProxyModel 并将modifyQuantity() 函数传回原始模型,对吗?
    • Delegate 只有在收到 dataChanged 等信号时才从模型中读取数据。因此它们通常不需要对列表对象的引用。您的一个解决方案是向您的模型添加一个额外的角色,该角色返回每个项目的唯一编号。然后,您可以在调用模型更改函数而不是索引时使用它。那么你就不必继承 QSortFilterProxyModel 了。
    • 这个想法的唯一问题是在模型中搜索唯一 ID 所需的时间,对吗?就我而言,这可能会很好,但我会不好意思走捷径。编辑:我走捷径。它工作得很好。该死的鼓励懒惰! (说真的,感谢您的见解!)