我想要一个名为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很聪明,在这种情况下不会不断重绘。但我不确定如何检查是否属实。
答案 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 = false
和recursive = 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
。如果由于其他原因没有必要,我会保持它不可见,因此它不会呈现两次。