【问题标题】:ListView.view is always null in ListView's delegateListView.view 在 ListView 的委托中始终为空
【发布时间】:2021-11-04 03:40:32
【问题描述】:

设置

我有一个带有一些通用模型的ListViewmyDelegate 组件。

ListView {
    id: myListView
    delegate: myDelegate
    ...
}

myDelegate组件中,我想设置ListViewcurrentItem。我目前是这样做的:

Component {
    id: myDelegate
    ...
    MouseArea {
        onClicked: myListView.currentIndex = model.index
    }
}

一切都按预期进行。

问题

众所周知,在委托中使用ListViewid 是不好的做法,因为可能有多个ListView 使用同一个委托组件。因此,应该使用ListView.view 附加属性。

但如果我像这样更改委托的代码:

Component {
    id: myDelegate
    ...
    MouseArea {
        onClicked: ListView.view.currentIndex = model.index
    }
}

我收到了TypeError: Value is null and could not be converted to an object

通过以下 console.logs,我发现 ListView.view 始终为空。我不明白为什么。在ListView 上设置currentIndex 本身也会失败。

onClicked: {
    console.log("ListView:", ListView)
    console.log("ListView.view:", ListView.view)
    console.log("ListView.currentIndex:", ListView.currentIndex)
}
...
qml: ListView: QQuickListViewAttached(0x6db0b30)
qml: ListView.view: null
qml: ListView.currentIndex: undefined

最小的可重现示例

Qt v6.2.1
Qt Creator 中的空 Qt Quick 项目
main.qml:

import QtQuick
import QtQuick.Window

Window {
    width: 150
    height: 350
    visible: true

    Component {
        id: myDelegate

        Rectangle {
            color: ListView.isCurrentItem ? "pink" : "lightblue"
            implicitWidth: 150
            implicitHeight: 50

            MouseArea {
                anchors.fill: parent
                onClicked: {
                    ListView.view.currentIndex = model.index
                    console.log("ListView", ListView)
                    console.log("ListView.view", ListView.view)
                }
            }

            Text {
                anchors.centerIn: parent
                text: model.index
            }
        }
    }

    ListView {
        id: myListView
        anchors.fill: parent
        spacing: 2
        model: 6
        delegate: myDelegate
    }
}

【问题讨论】:

标签: qt listview qml qt-quick


【解决方案1】:

附加属性设置在委托的根目录中,因此如果您想从子项访问,则必须使用根目录作为参考:

    Component {
        id: myDelegate

        Rectangle {
            id: root_delegate // <---

            color: ListView.isCurrentItem ? "pink" : "lightblue"
            implicitWidth: 150
            implicitHeight: 50

            MouseArea {
                anchors.fill: parent
                onClicked: {
                    root_delegate.ListView.view.currentIndex = model.index;
                    console.log("ListView", root_delegate.ListView);
                    console.log("ListView.view", root_delegate.ListView.view);
                }
            }

            Text {
                anchors.centerIn: parent
                text: model.index
            }

        }

    }

【讨论】:

  • 这种行为很奇怪,因为声明的属性可以直接从子级访问...
  • @DmitrySemenov 显式优于隐式,使用ids来引用其他对象的属性或方法,除了更容易阅读代码,避免出现此类bug
猜你喜欢
  • 2020-04-13
  • 2021-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多