Qt 如何根据QML中不同QAbstractListModel的元素实现列表?

Qt 如何根据QML中不同QAbstractListModel的元素实现列表?,qt,qml,qabstractitemmodel,Qt,Qml,Qabstractitemmodel,在QML中,我想指定一个选项(字符串)列表,用户可以选择将其插入我的后端。但是我不希望列表中包含的字符串在后端已经。如果后端已更新,则选项列表也应更新 首先,我编写了一个子类QAbstractListModel,它为我的后端公开了QString接口的列表。它遵循文档中的指导原则,并公开了两个自定义函数push_back和indexOf class MyModel: public QAbstractListModel { Q_OBJECT public: MyModel() { .

在QML中,我想指定一个选项(字符串)列表,用户可以选择将其插入我的后端。但是我不希望列表中包含的字符串在后端已经。如果后端已更新,则选项列表也应更新

首先,我编写了一个子类
QAbstractListModel
,它为我的后端公开了
QString
接口的列表。它遵循文档中的指导原则,并公开了两个自定义函数
push_back
indexOf

class MyModel: public QAbstractListModel {
    Q_OBJECT
public:
    MyModel() { ... } // connect to the backend

    QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override {
        Q_UNUSED(role);
        if (!hasIndex(index.row(), index.column())) {
            return {};
        }
        return ... // retreive backend object at index.row() and convert to QString
    }


    Q_INVOKABLE void push_back(const QString& item) {
        beginInsertRows(QModelIndex(), int(_data->size()), int(_data->size()));

        ... // convert QString to backend data type and insert into backend

        endInsertRows();
    }

    Q_INVOKABLE int indexOf(const QString& item) {
        return ... // convert QString to backend type, and search backend for this object. return -1 if not found
    }


private:
    // pointer to backend object
};
在我的QML中,我也在想类似的事情。首先是后端中已经存在的字符串的视图。这部分很好用

ListView {
  anchors.fill: parent
  spacing: 5
  model: backend // an instance MyModel interface, passed in from main.cpp

  delegate: Rectangle {
    height: 25
    width: 200
    Text { text: model.display}
  }
}
然后是可以添加到后端的选项列表,这些选项还不是后端的一部分。这部分不行

ListView {
  anchors.fill: parent
  spacing: 5
  model: ["option1", "option2", "option3"]

  delegate: Rectangle {
    visible: backend.indexOf(model.modelData) >= 0
    height: 25
    width: 200
    MouseArea {
        id: mouseArea1
        anchors.fill: parent
        onClicked: {
            backend.push_back(model.modelData)
        }
    }
    Text { text: model.modelData }
  }
}

问题是,将字符串添加到后端时,此列表不会刷新。我认为Qt不理解,每当修改
backend.indexOf
时,都需要重新计算它。

关于这个问题,您是正确的。没有将重新调用indexOf的绑定。解决此问题的一种方法是,可以添加Connections对象,以便侦听特定信号,然后手动更新visible属性:

  delegate: Rectangle {
    visible: backend.indexOf(model.modelData) >= 0
    height: 25
    width: 200
    MouseArea {
        id: mouseArea1
        anchors.fill: parent
        onClicked: {
            backend.push_back(model.modelData)
        }
    }
    Text { text: model.modelData }

    Connections {
      target: backend
      onCountChanged: visible = (backend.indexOf(model.modelData) >= 0)
    }
  }

关于这个问题你是对的。没有将重新调用indexOf的绑定。解决此问题的一种方法是,可以添加Connections对象,以便侦听特定信号,然后手动更新visible属性:

  delegate: Rectangle {
    visible: backend.indexOf(model.modelData) >= 0
    height: 25
    width: 200
    MouseArea {
        id: mouseArea1
        anchors.fill: parent
        onClicked: {
            backend.push_back(model.modelData)
        }
    }
    Text { text: model.modelData }

    Connections {
      target: backend
      onCountChanged: visible = (backend.indexOf(model.modelData) >= 0)
    }
  }


为什么你不从添加到C++模型的QML模型中移除这个元素呢?后端也可以通过其他方式来更新。例如,加载配置文件或按“重置为默认值”按钮。那么这些功能也必须以某种方式进入这个列表并同步它。嗯,我认为你的帖子没有涵盖你在前面评论中指出的所有内容。例如,通过QML,您选择“opt1”选项,这样它将被添加到后端,它将不可见(或删除),但然后从C++(或其他方式)“opt1”被删除,在这种情况下,它是否应该在ListVIEW中被“可见”opt1?如果后端通过替换的方式改变,则<代码> EnEntIdTrUTWSW()将调用或EndRemoveOws()。Qt可以使用此信号来知道它应该重新计算依赖于模型的表达式,例如
backend.indexOf(…)
。这将更新已插入或删除的选项的可见性。这是您假定的,但QML不是这样工作的。时隙(或QyNoWoCube)不会生成与QML属性的绑定,因此“可见”属性没有更新,为什么不从添加到C++模型中的QML模型中移除元素?例如,加载配置文件或按“重置为默认值”按钮。那么这些功能也必须以某种方式进入这个列表并同步它。嗯,我认为你的帖子没有涵盖你在前面评论中指出的所有内容。例如,通过QML,您选择“opt1”选项,这样它将被添加到后端,它将不可见(或删除),但然后从C++(或其他方式)“opt1”被删除,在这种情况下,它是否应该在ListVIEW中被“可见”opt1?如果后端通过替换的方式改变,则<代码> EnEntIdTrUTWSW()将调用或EndRemoveOws()。Qt可以使用此信号来知道它应该重新计算依赖于模型的表达式,例如
backend.indexOf(…)
。这将更新已插入或删除的选项的可见性。这是您假定的,但QML不是这样工作的。插槽(或Q_INVOKABLES)不会生成与QML属性的绑定,因此“visible”属性不会更新这看起来是一个很好的解决方法。我尝试了一下,得到了
qrc:/main.qml:127:19:qml连接:连接中隐式定义的onFoo属性不推荐使用。改为使用此语法:function onFoo(){…}qrc:/main.qml:127:19:qml Connections:无法分配给不存在的属性“onCountChanged”
是否
countChanged
是我应该实现的自定义信号?好的,我使用此处的语法修复了不推荐的消息,然后实现了
changed()
作为自定义信号,它起作用了!是的,在5.15版本中,不推荐使用的消息是一个恼人的添加。我不知道他们为什么改变语法。对于
onCountChanged
,我假设您的模型在插入项目时已经发出了该信号,但是是的,任何信号都可以。我还必须将height属性更改为负值(否定
间距
值),以弥补剩余的空白。这看起来是一个很好的解决方法。我尝试了一下,得到了
qrc:/main.qml:127:19:qml连接:连接中隐式定义的onFoo属性不推荐使用。改为使用此语法:function onFoo(){…}qrc:/main.qml:127:19:qml Connections:无法分配给不存在的属性“onCountChanged”
是否
countChanged
是我应该实现的自定义信号?好的,我使用此处的语法修复了不推荐的消息,然后实现了
changed()
作为自定义信号,它起作用了!是的,在5.15版本中,不推荐使用的消息是一个恼人的添加。我不知道他们为什么改变语法。对于
onCountChanged
,我假设您的模型在插入项目时已经发出了该信号,但是是的,任何信号都可以。我还必须将height属性更改为负值(否定
间距
值),以弥补剩余的空白。