如何在 QtQuick2 中正确实现可检查的 ListView? [英] How to correctly implement a checkable ListView in QtQuick2?

查看:43
本文介绍了如何在 QtQuick2 中正确实现可检查的 ListView?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

来自 C++ 我不知道如何在 QtQuick 中正确实现可检查的 ListView.

Coming from C++ I dont know how to correctly implement a checkable ListView in QtQuick.

出于测试目的,我创建了一个小型测试应用程序.

For testing purposes I created a small test application.

模型:

class MyModel : public QAbstractListModel
{
    Q_OBJECT

public:
    MyModel(QObject *parent = Q_NULLPTR) :
        QAbstractListModel(parent)
    {
        for(int i = 0; i < 10; i++)
            m_items.insert(QString("item%0").arg(i), qrand() % 2 == 0 ? Qt::Checked : Qt::Unchecked);
    }

    int rowCount(const QModelIndex& parent) const Q_DECL_OVERRIDE
    {
        return m_items.count();
    }

    QVariant data(const QModelIndex& index, int role) const Q_DECL_OVERRIDE
    {
        if(index.row() >= m_items.count())
            return QVariant();

        auto key = m_items.keys().at(index.row());

        switch(role)
        {
        case Qt::DisplayRole:
            return key;
        case Qt::CheckStateRole:
            return m_items[key];
        }

        return QVariant();
    }

    bool setData(const QModelIndex& index, const QVariant& value, int role) Q_DECL_OVERRIDE
    {
        qDebug() << "setData()" << index.row() << value << role;

        switch(role)
        {
        case Qt::CheckStateRole:
        {
            auto key = m_items.keys().at(index.row());
            m_items[key] = value.value<Qt::CheckState>();
            emit dataChanged(index, index, QVector<int> { Qt::CheckStateRole });
            return true;
        }
        }

        return QAbstractListModel::setData(index, value, role);
    }

    Qt::ItemFlags flags(const QModelIndex& index) const Q_DECL_OVERRIDE
    {
        Qt::ItemFlags f = QAbstractListModel::flags(index);
        if(index.isValid())
            f |= Qt::ItemIsUserCheckable;
        return f;
    }

    QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE
    {
        return QHash<int, QByteArray> {
            { Qt::DisplayRole, QByteArrayLiteral("display") },
            { Qt::CheckStateRole, QByteArrayLiteral("checkState") },
        };
    }

private:
    QMap<QString, Qt::CheckState> m_items;
};

在运行时,我创建了一个 QListView 小部件和一个 ListView QtQuick2 项目.两者都连接到同一个模型.

On runtime I create a QListView widget and a ListView QtQuick2 item. Both are attached to the same model.

在小部件中选中/取消选中时,qml 视图会正确更新.在 qml 视图中选中/取消选中时,widget 视图不会改变!

When checking/unchecking in the widget, the qml view gets updated correctly. When checking/unchecking in the qml view, the widget view does not change!

我注意到我的 setData 没有被调用.

I noticed that my setData is not being called.

在 QtQuick2 中实现可检查 ListView 的正确方法是什么?

What is the correct way to implement a checkable ListView in QtQuick2?

ListView {
    anchors.fill: parent

    model: __myModel

    delegate: CheckDelegate {
        text: model.display
        checked: model.checkState
    }
}

推荐答案

问题确实在于 CheckDelegate 没有自动调用 setData.你必须告诉它这样做.为此,您可以使用 toggled 信号 :

The problem is indeed that the CheckDelegate doesn't call setData automatically. You have to tell it to do that. For this you can use the toggled signal :

delegate: CheckDelegate {
    text: model.display
    checked: model.checkState
    onToggled: model.checkState = checked // this will call setData for CheckStateRole
}

这篇关于如何在 QtQuick2 中正确实现可检查的 ListView?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆