如何在 QtQuick2 中正确实现可检查的 ListView?

How to correctly implement a checkable ListView in QtQuick2?

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

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

型号:

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 项目。两者都附在同一个模型上。

当小部件 checking/unchecking 时,qml 视图会正确更新。 checking/unchecking在qml视图时,widget视图没有变化!

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

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

ListView {
    anchors.fill: parent

    model: __myModel

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

问题确实是 CheckDelegate 没有自动调用 setData。 你必须告诉它这样做。为此,您可以使用 toggled signal :

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