从 QML ListView 操作 QAbstractListModel 中的数据

新手上路,请多包涵

我有一个使用 QAbstractListModel 子类作为模型的 QML ListView。

 ListView {
    id: myListView
    x: 208
    y: 19
    width: 110
    height: 160
    delegate: myListDelegate {}
    model: MyListModel
    opacity: 0
}

该模型是 MyListItem s 的列表。

 class MyListModel : public QAbstractListModel
{
    Q_OBJECT
public:
    enum MyRoles {
        HeadingRole = Qt::UserRole + 1,
        DescriptionRole,
        QuantityRole
    };

    explicit MyListModel(QObject *parent = 0);

    void addMyListItem(const MyListItem &item);
    int rowCount(const QModelIndex & parent = QModelIndex()) const;
    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
    void dropList();

private:
    QList<MyListItem> m_list;

};

在代表中,我有一个鼠标区域。

如何拦截鼠标区域的点击并从我的 QList 模型 中选择 MyListItem 并将其发送到应用程序的 C++ 部分中的某个位置?

原文由 Zhigalin - Reinstate CMs 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

您还可以在委托中使用 index 属性来操作数据。您只需使用模型上的 index 方法将 QML 索引转换为 QModelIndex 。这是一个简单的示例,每次单击列表项时,我们将显示值更改为字符串“3”。

 ListView {
    id: listView
    anchors.fill: parent
    model: my_model

    delegate: Rectangle {
        height: 50
        width: listView.width

        MouseArea {
            anchors.fill: parent
            onClicked: {
                // Column is always zero as it's a list
                var column_number = 0;
                // get `QModelIndex`
                var q_model_index = my_model.index(index, column_number);

                // see for list of roles:
                // http://doc.qt.io/qt-5/qabstractitemmodel.html#roleNames
                var role = 1

                var data_changed = my_model.setData(q_model_index, "3", role);

                console.log("data change successful?", data_changed);
            }
        }
    }
}

除了委托中的 index 属性之外,委托中的所有默认角色名称都可用。例如,我之前使用 decoration 角色来设置我的 Rectangle 委托的 color 属性。有关更多信息,请参阅 此列表

 ListView {
    delegate: Rectangle {
        // list items have access to all default `roleNames`
        // in addition to the `index` property.
        // For example, using the decoration role, demo'd below
        color: decoration
    }
}

另请参阅 Mitch Curtis 建议使用 qmlRegisterUncreatableType 注册用户枚举的 链接

原文由 Ben Hoff 发布,翻译遵循 CC BY-SA 4.0 许可协议

评论提到将指向 MyListItemdata() 的指针返回到 QML 并在 QML 中访问和修改它。这需要您的 MyListItem 继承自 QObject 并为您要在 QML 中访问的每个成员添加一个 Q_PROPERTY 。它还需要密切注意对象的所有权( QQmlEngine::ObjectOwnership )。

还有一种方法:实现 QAbstractListModel::setData()QAbstractListModel::roleNames() ,模型内容可以从 QML 改变,比如 model.roleName = foo

下面的最小工作示例,每次单击委托时数量加倍:

C++:

 struct MyListItem
{
    QString heading;
    QString description;
    int quantity;
};

class MyListModel : public QAbstractListModel
{
    Q_OBJECT
    Q_ENUMS(MyRoles)
public:
    enum MyRoles {
        HeadingRole = Qt::UserRole + 1,
        DescriptionRole,
        QuantityRole
    };

    using QAbstractListModel::QAbstractListModel;

    QHash<int,QByteArray> roleNames() const override {
        return { { HeadingRole, "heading" },
            { DescriptionRole, "description" },
            { QuantityRole, "quantity" },
        };
    }
    int rowCount(const QModelIndex & parent = QModelIndex()) const override {
        if (parent.isValid())
            return 0;
        return m_list.size();
    }

    bool setData(const QModelIndex &index, const QVariant &value, int role) override
    {
        if (!hasIndex(index.row(), index.column(), index.parent()) || !value.isValid())
            return false;

        MyListItem &item = m_list[index.row()];
        if (role == DescriptionRole) item.description = value.toString();
        else if (role == HeadingRole) item.heading = value.toString();
        else if (role == QuantityRole) item.quantity = value.toInt();
        else return false;

        emit dataChanged(index, index, { role } );

        return true ;

    }

    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override {
        if (!hasIndex(index.row(), index.column(), index.parent()))
            return {};

        const MyListItem &item = m_list.at(index.row());
        if (role == DescriptionRole) return item.description;
        if (role == HeadingRole) return item.heading;
        if (role == QuantityRole) return item.quantity;

        return {};
    }

private:
    QVector<MyListItem> m_list = {
        { "heading 1", "description 1", 1 },
        { "heading 2", "description 2", 42 },
        { "heading 3", "description 3", 4711 }
    };
};

QML:

 ListView {
    id: listView
    anchors.fill: parent
    model: MyListModel {}

    delegate: Item {
        implicitHeight: text.height
        width: listView.width
        Text {
            id: text
            text: model.heading + " " + model.description + " " + model.quantity
        }

        MouseArea {
            anchors.fill: text
            onClicked: {
                model.quantity *= 2;
            }
        }
    }
}

原文由 Thomas McGuire 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题