当我在onStateChanged

时间:2017-03-29 18:15:26

标签: qt caching recursion qml qtquick2

我想要一个名为ShaderEffectSource的{​​{1}}更新源项的每次更改,但是当源项被销毁时,我希望snapshotter保留源的最后一个状态项目

在我的代码中,我使用a workaround for a Qt deficiency - 在前一个源项被销毁时设置snapshotter。当我销毁旧的源项目时,这样可以正常,例如在按键上。但是当我在snapshotter.sourceItem = snapshotter处理程序中执行此操作时,我收到此错误:

  

ShaderEffectSource:递归渲染时,'recursive'必须设置为true。

但我不想设置onStateChanged,因为recursive: true会尽快开始重新绘制,浪费了大量的处理能力。

知道为什么会出现这种问题考虑到使用按键和/或解决方法时效果正常?

我意识到我问为什么 hacky解决方案在某些情况下会失败,但由于它在某些情况下有效,我还是想使用该解决方案,因为它非常有用。

我的代码:(main.qml)

snapshotter

注意:我刚才有一个想法:设置import QtQuick 2.6 import QtQuick.Window 2.2 Window { visible: true width: 640 height: 480 Loader { active: true id: loader sourceComponent: Rectangle { color: "red" border.color: "white" width: 100 height: 100 parent: row states: [ State { // the condition is always true, in this example code name: "theOnlyState"; when: width === 100 } ] onStateChanged: { if(state === "theOnlyState") { loader.active = false; } } } } Row { id: row ShaderEffectSource { id: snapshotItem sourceItem: { if(loader.status === Loader.Ready) { return loader.item; } else { return snapshotItem; } } live: loader.status === Loader.Ready width: 100 height: 100 } } } 可能不会产生我提到的问题,考虑到我只在recursive: true时设置它。也许Qt很聪明,在这种情况下不会不断重绘。但我不确定如何检查是否属实。

2 个答案:

答案 0 :(得分:0)

好的,我找到了99%的答案。

我在问题中表达的对recursive: true的担忧是由于我在Qt文档中阅读类似内容的模糊记忆而引起的。

我现在继续向上查看relevant passage,这就是它的内容:

  

将此属性和live都设置为true将导致场景图形连续渲染。由于ShaderEffectSource依赖于自身,因此更新它意味着它会立即再次变脏。

请注意他们如何说出错误的情况,live必须是true

所以解决方案是简单地使用recursive: true,这使得解决方案更加简洁。

注意:我不会接受这个答案,因为我希望人们不时地过去,也许,也许,只是也许,证明我错了(例如,表明我错误解释了文本。

支持上述结论的更多证据:

我将env var QSG_VISUALIZE设置为changes并运行此trivival测试应用程序:

import QtQuick 2.6
import QtQuick.Window 2.2

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

    ShaderEffectSource {
        width: 100
        height: 100
        id: shaderEffectSource
        live: false
        sourceItem: shaderEffectSource
        recursive: true
    }
}

它显示了一个不变的彩色方块。但是当我在此代码中将live更改为true时,它开始以随机颜色闪烁。

答案 1 :(得分:0)

当您发现自己时,当您live = falserecursive = true时,它将不会一直重新绘制。

我认为您的问题可能是由magic引起的,QML用于其状态机,来回等等......

据我了解您的问题,您想要创建一个对象,拍摄快照,然后再将其删除。
通过使用方法和信号比通过某些声明性状态更改等更容易实现这一点。

具体而言,您可能正在寻找scheduleUpdate()来渲染下一帧,而无需设置live = true。接下来你会感兴趣的是信号:scheduledUpdateCompleted再次删除你的对象。

这样的事情:

import QtQuick 2.0
import QtQuick.Controls 2.0
import QtGraphicalEffects 1.0
ApplicationWindow {
    width: 1024
    height: 800
    visible: true

    Button {
        text: 'Next'
        onClicked: {
            ses.sourceItem = prototype.createObject(ses)
        }
    }

    ShaderEffectSource {
        id: ses
        y: 100
        width: 50
        height: 50
        live: false
        onSourceItemChanged: if (sourceItem !== this) scheduleUpdate()
        onScheduledUpdateCompleted: {
            sourceItem.destroy()
            sourceItem = this
        }
    }

    Component {
        id: prototype
        Rectangle {
            width: 50
            height: 50
            color: Qt.rgba(Math.random(-1), Math.random(0), Math.random(1))
            visible: false
            Component.onCompleted: console.log('Created new Rectangle with color', color)
            Component.onDestruction: console.log('Destroy Rectangle with color', color)
        }
    }
}

请记住: sourceItem无需显示为ShaderEffectSource。如果由于其他原因没有必要,我会保持它不可见,因此它不会呈现两次。