0

我正在制作有关 Sailfish OS 的电视指南,但目前遇到了一个障碍。因为我希望有可能为自定义列表标记每个条目,所以我需要修改后面的模型。我曾尝试直接修改模型: model.favorite = true但这不起作用。我试图修改底层 arrayOfObjects,但这并没有反映在 UI 中,并且我无法触发更新,因为我无法访问 ListView。我曾尝试制作自定义模型,但由于我无法引用它的实例,因此无济于事。

下面是一个非常简化的布局表示,主要使用基本的 QML。

Page {
    Flickable {
        Column {
            SlideshowView { // PathView
                model: arrayOfObjects
                delegate: channelDelegate
            }
        }
    }

    Component {
        id: channelDelegate
        ListView {
            id: channelList
            // ProgramModel just iterates thru arrayOfObjects and appends them
            model: ProgramModel {
                programs: arrayOfObjects
            }
            delegate: programDelegate
            Component.onCompleted: {
                // I can't reference channelList from here.
            }
        }
    }

    Component {
        id: programDelegate
        ListItem {
            Button {
                onClicked: {
                    // How do I reference channelList?
                    // Doing it by name doesn't work.
                }
            }
        }
    }
}

我曾尝试调用 ApplicationWindow (有效),以发送我在 channelList.onCompleted (也有效)中连接的信号,但由于我无法从那里引用列表,因此无济于事。

我在 QT 5.6 上,所以有些解决方案可能不起作用。而且我真的更喜欢保持纯 QML;没有 C++。

4

2 回答 2

1

我无法准确重现您的案例,但也许这个快速示例可以帮助您。

import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 2.2

Window {
    id: mainWrapper
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    signal updateModel(int id, string name)

    Component {
        id: listWrapper

        ListView {
            id: list

            model: [
               { name: "name0" },
               { name: "name1" },
               { name: "name2" }
           ]

            delegate: Loader {
                width: parent.width
                property variant model: modelData
                property int modelIndex: index
                sourceComponent: listDelegate
            }

            function updateModelName(id, name) {
                var listModel = list.model
                listModel[id].name = name
                list.model = listModel
            }
        }
    }

    Loader {
        id: loadedList
        x: 0
        anchors.fill: parent
        sourceComponent: listWrapper

        Component.onCompleted: {
            mainWrapper.updateModel.connect(loadedList.item.updateModelName)
        }
    }

    Component {
        id: listDelegate

        Rectangle {
            id: listRow
            width: 200
            height: 80
            Text {
                text: model.name
            }

            Button {
                x: 100
                text: "update"
                onClicked: {
                    mainWrapper.updateModel(modelIndex, "better_name"+modelIndex)
                }
            }
        }
    }
}

这个例子的线索是使用信号和函数来更新模型。

于 2019-12-17T12:39:11.160 回答
0

因为 SlideshowView 替换了 DaszuOne 回答中的焦点,即切换幻灯片,list.model = listModel导致整个视图发生变化。更改模型中的单个条目不会触发更新,因此需要更多代码才能实现。所以在反复考虑之后,我决定用“正确的方式”做这件事,比用简单的方法做起来更麻烦、更难读。

我做了一个非常简单的包装器,它可以使用您使用的哪种持久存储,只有两种方法:setFavorite()isFavorite.

在委托中,我更新了 onCompleted 中的属性,因此每次需要渲染元素时都会调用它:

    Component.onCompleted: {
        favorite = favorites.isFavorite(model.channelId, model.id)
    }

我的结论是,DaszuOne 的答案是正确的答案——但在这种情况下不是;)

感谢您的所有帮助,它让我更好地理解了 QML。

于 2019-12-19T09:37:52.403 回答