PDA

View Full Version : Spurious "Binding loop detected" warnings [solved]



pherthyl
24th May 2013, 19:43
I have a qml item that presents a stimulus (image and sound) on the screen on a timer.
So I have a stimulus state as such:

State {
name: "stimulus"
extend: "running"
PropertyChanges {
target: getStimulus()
explicit: true
present: true
}
}

This state is entered when a timer fires. The getStimulus() function returns the stimulus item that I would like to present. It looks like this:

function getStimulus() {
console.log("GetStimulus() currIndex: "+currIndex+" value: "+sequence[currIndex])
var stimIndex = 0
if(sequence[currIndex] === 0) {// non-target
stimIndex = 1+Math.floor(Math.random()*(stimuli.children.lengt h-1))
}
return stimuli.children[stimIndex]
}

As you can see, when the sequence of stimuli specifies a distractor stimulus, the function chooses a random one amongst the children of an Item that holds them.

This works perfectly with no warnings.

However now I want to prevent the same distractor stimulus being shown twice in a row. So I did this:


function getStimulus() {
console.log("GetStimulus() currIndex: "+currIndex+" value: "+sequence[currIndex])
var stimIndex = 0
if(sequence[currIndex] === 0) {// non-target
do { // FIXME this prints out spurious "Binding loop detected" warnings. Could rewrite by picking the index out of an array and removing the previous one.
stimIndex = 1+Math.floor(Math.random()*(stimuli.children.lengt h-1))
} while (stimIndex === lastStimIndex);
lastStimIndex = stimIndex
}
return stimuli.children[stimIndex]
}


This works exactly as I want it to, however on the console it prints out: QML PropertyChanges: Binding loop detected for property "target"
Not really a functionality problem, but this is very annoying. How do I avoid this warning? There is no actual binding loop here, there just happens to be a loop in the function to find the target.

Oddly enough, when I rewrote the function with an alternate method based on selecting the index out of an array, the binding loop warning is still there.

wysota
24th May 2013, 20:10
"target: getStimulus()" is a binding, not an assignment, thus whenever the value of this function changes, target gets updated. I cannot say what exactly happens in your particular case (most likely because QML detects that stimIndex has influence on the return value of the function) but you can most probably solve it by assigning a value to target manually instead of binding it to a function (e.g. when transiting out of the state you can execute a function that will calculate the new value and assign it to target of the PropertyChanges element.

Another solution would be to simply shuffle the array of candidates and increase the index in the array until you reach the end of it and then simply shuffle the array again and start from the beginning.

pherthyl
24th May 2013, 23:16
Thanks. I initially had a property called currentStimulus as the fixed target, and then assigned it in another state, but the code seemed a bit confusing/not as direct.
You say I could execute a function when transitioning out of that state.. Is there a way to associate a script on state exit, or would it be a StateChangeScript for the following state?

Added after 19 minutes:

Solved by pre-calculating the random sequence in C++ and just reading it back out of an array.


function getStimulus() {
return stimuli.children[sequence[currIndex]]
}

wysota
25th May 2013, 08:22
Is there a way to associate a script on state exit, or would it be a StateChangeScript for the following state?

transitions: Transition { from: "stimulus"; ScriptAction { script: doSomething(); }}