获取QList对象的ListView索引

Getting the ListView index of a QList object

本文关键字:ListView 索引 对象 QList 获取      更新时间:2023-10-16

我已经将QList<MyItem*>暴露为ListView的模型。但是我怎样才能得到一个MyItem*对象的ListView索引呢?

上下文:我在c++中创建了一个findObject()函数,当我找到对象(MyItem*)时,我想滚动到ListView中的相应项目。

一些代码(完整的源代码和Qt Creator项目可以在https://github.com/joncol/qml_test找到)。

项目类:

class MyItem : public QObject
{
    Q_OBJECT
    Q_PROPERTY(qint32 data READ data NOTIFY dataChanged)
public:
    MyItem() : m_data(s_counter++) {}
    quint32 data() const { return m_data; }
signals:
    void dataChanged();
private:
    static int s_counter;
    int m_data;
};

模型:

class MyCppModel : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QQmlListProperty<MyItem> itemList READ itemList NOTIFY itemListChanged)
public:
    MyCppModel()
    {
        m_specialItem = new MyItem;
        m_model.append(new MyItem);
        m_model.append(new MyItem);
        m_model.append(new MyItem);
        m_model.append(m_specialItem);
        m_model.append(new MyItem);
    }
    QQmlListProperty<MyItem> itemList()
    {
        return QQmlListProperty<MyItem>(this, m_model);
    }
    Q_INVOKABLE QVariant specialItem()
    {
        return QVariant::fromValue(m_specialItem);
    }
signals:
    void itemListChanged();
private:
    QList<MyItem*> m_model;
    MyItem* m_specialItem; // simulate found item
};

main函数:

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QQmlApplicationEngine engine;
    QQmlContext* c = engine.rootContext();
    MyCppModel* myCppModel = new MyCppModel;
    c->setContextProperty("myCppModel", myCppModel);
    qmlRegisterUncreatableType<MyItem>("CppModel", 1, 0, "MyItem", "");
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    return app.exec();
}

最后是QML:

ApplicationWindow {
    title: qsTr("Testing")
    width: 640
    height: 480
    visible: true
    ColumnLayout {
        anchors.centerIn: parent
        Rectangle {
            width: 150
            height: 25
            color: "#e67e22"
            border.width: 1
            border.color: "black"
            Text {
                anchors.centerIn: parent
                text: "Mark Special Item"
            }
            MouseArea {
                anchors.fill: parent
                onClicked: {
                    var item = myCppModel.specialItem()
                    console.debug("how to color the special item: " + item)
                }
            }
        }
        ListView {
            id: itemList
            width: 200
            height: 25 * count
            model: myCppModel.itemList
            delegate: Item {
                width: parent.width
                height: 25
                Rectangle {
                    width: parent.width
                    height: 20
                    color: "#34495e"
                    border.width: 1
                    border.color: "black"
                    Text {
                        x: 10
                        anchors.verticalCenter: parent.verticalCenter
                        text: modelData.data
                        color: "white"
                    }
                }
            }
        }
    }
}

有几种方法可以做到这一点,这取决于您的应用程序逻辑。

1。添加isSpecialItem属性到MyItem

class MyItem : public QObject
{
    Q_OBJECT
    Q_PROPERTY(qint32 data READ data NOTIFY dataChanged)
    Q_PROPERTY(bool isSpecialItem READ isSpecialItem WRITE setIsSpecialItem NOTIFY isSpecialItemChanged)
    // ...
}

你的委托看起来像这样:

Rectangle {
    width: parent.width
    height: 20
    color: "#34495e"
    border.width: 1
    border.color: isSpecialItem ? "red" : "black"
    Text {
        x: 10
        anchors.verticalCenter: parent.verticalCenter
        text: modelData.data
        color: "white"
    }
}

这是最简单的方法,但是用一些您可能认为更特定于ui的东西污染MyItem

2。使MyCppModel派生自QAbstractItemModel

使用此选项,您可以在委托中使用SpecialItem角色,委托的QML代码与选项#1相同。

我认为这是解决这个问题的规范方法,特别是如果itemList不需要成为QQmlListProperty。它不需要将潜在的ui特定isSpecialItem属性添加到MyItem,并且可以以与当前存储它相同的方式存储;在data()函数中,可以这样写:

if (role == SpecialItem) {
    return QVariant(m_specialItem == m_model.at(index.row()));
}

3。将特殊项公开为列表

的索引属性。

要这样做,您需要将specialItem()函数转换为MyCppModel的属性:

Q_PROPERTY(int specialItemIndex READ specialItemIndex WRITE specialItemIndex NOTIFY specialItemIndexChanged)

然后,你的委托将看起来非常类似于选项2,除了一行:

border.color: myCppModel.specialItemIndex == index ? "red" : "black"