How to correctly implement a checkable ListView in QtQuick2?

北慕城南 提交于 2019-12-11 06:54:36

问题


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

For testing purposes I created a small test application.

The model:

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;
};

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

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!

I noticed that my setData is not being called.

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
    }
}

回答1:


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
}


来源:https://stackoverflow.com/questions/45194359/how-to-correctly-implement-a-checkable-listview-in-qtquick2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!