QML 在不重新加载内容的情况下更改 Pathview 的路径

QML changing Pathview's path without reloading content

我遇到了 Pathview 的问题。我需要更改路径 属性 以重新组织子项目,但是当我这样做时,它会导致所有创建的元素(由模型指定)被销毁并重新创建。

有没有什么方法可以在不重新加载内容的情况下做到这一点,或者 'cover' 闪烁效果?

示例:

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

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("PathView path test")

    Path {
        id: path1
        startX: 100; startY: 100
        PathLine{ x: 300; y: 100 }
    }
    Path {
        id: path2
        startX: 100; startY: 100
        PathLine{ x: 100; y: 300 }
    }

    ListModel {
        id: pvModel
        ListElement{ name: "rectangle" }
        ListElement{ name: "rectangle" }
        ListElement{ name: "rectangle" }
    }

    Component {
        id: pvDelegate
        Rectangle {
            width: 50
            height: 50
            color: "red"
            border.width: 1
            Component.onCompleted: console.log("Rectangle created")
            Component.onDestruction: console.log("Rectangle deleted")
        }
    }

    property bool currentPath;
    PathView {
        anchors.fill: parent
        model: pvModel
        delegate: pvDelegate
        path: (currentPath ? path1 : path2)
    }

    Button {
        width: 100
        height: 40
        text: "Switch path"
        onClicked: currentPath = !currentPath
    }
}

我不知道它是否只是上述测试用例中的路径,或者这是否适用于您在真实应用程序中的路径,但一种选择是更改路径的属性而不是改变整个路径。看起来您甚至可以为路径属性设置动画:

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

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("PathView path test")

    Path {
        id: pvPath
        startX: 100; startY: 100
        PathLine{
            x: currentPath ? 300 : 100
            y: currentPath ? 100 : 300
            Behavior on x { SmoothedAnimation { duration: 125 } }
            Behavior on y { SmoothedAnimation { duration: 125 } }
        }
    }

    ListModel {
        id: pvModel
        ListElement{ name: "rectangle" }
        ListElement{ name: "rectangle" }
        ListElement{ name: "rectangle" }
    }

    Component {
        id: pvDelegate
        Rectangle {
            width: 50
            height: 50
            color: "red"
            border.width: 1
            Component.onCompleted: console.log("Rectangle created")
            Component.onDestruction: console.log("Rectangle deleted")
        }
    }

    property bool currentPath;
    PathView {
        anchors.fill: parent
        model: pvModel
        delegate: pvDelegate
        path: pvPath
    }

    Button {
        width: 100
        height: 40
        text: "Switch path"
        onClicked: currentPath = !currentPath
    }
}

PathView 似乎使用了这个技巧,在 Path 更改后强制重新布局。到目前为止,我没有找到理想的方法来执行此操作,但是要阻止 PathView 破坏您的代表,可以通过使用中间 DelegateModel.

来完成

DelegateModelview 实例化 Item,您可以选择将 Item 添加到 persistedItems-group.

因为我们可能想要使用模型的动态实例化,对于这个例子,我只添加那些 Items 到这个组,当 Path 将切换时,实例化,并在切换后立即将它们从组中删除。

正如我所说:我没有找到(但并没有寻找太多)强制重新布局的好方法。所以目前,我稍微移动了视图,否则代表的 x 和 y 值将不会更新。

如果您的所有 Item 无论如何都可见,您可以在 Component.onCompleted-slot

中将它们全部标记为 persistent
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 1.2
import QtQml.Models 2.2

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("PathView path test")

    Path {
        id: path1
        startX: 100; startY: 100
        PathLine{ id: line1; x: 300; y: 100 }
    }
    Path {
        id: path2
        startX: 100; startY: 100
        PathLine{ x: 100; y: 300 }
    }

    ListModel {
        id: pvModel
        ListElement{ name: "rectangle" }
        ListElement{ name: "rectangle" }
        ListElement{ name: "rectangle" }
    }

    DelegateModel {
        id: pvDelegateModel
        model: pvModel
        delegate: Rectangle {
            id: delegate
            width: 50
            height: 50
            color: 'red'
            border.width: 1

            Component.onCompleted: console.log("Rectangle created")
            Component.onDestruction: console.log("Rectangle destroyed")
            Connections {
                target: button
                onStart: delegate.DelegateModel.inPersistedItems = true // Make them persistent befor the switch 
                onEnd: delegate.DelegateModel.inPersistedItems = false // Make them non-persistent after the switch
            }
        }
    }

    PathView {
        id: pv
        anchors.fill: parent
        model: pvDelegateModel
        path: path1
        clip: true
    }

    Button {
        id: button
        width: 100
        height: 40
        text: "Switch path"
        signal start
        signal end
        onClicked: {
            start()
            pv.path = (pv.path === path1 ? path2 : path1)
            end()
            pv.currentIndex +=1   // To force a refresh of the layout
            pv.currentIndex -= 1
        }
    }
}