Property variant lose type information?
-
Hello!
Let's see app example:
@import QtQuick 1.1
Rectangle {
width: 300; height: 250; focus: true
Row {
Rectangle {
id: b1; width: 100; height: 62; color: "lightblue"
Keys.onPressed: console.log("Rectangle1::pressed")
Text {
text: "label1"
anchors.centerIn: parent
}
}
Rectangle {
id: b2; width: 100; height: 62; color: "lightgreen"
Keys.onPressed: console.log("Rectangle2::pressed")
Text {
text: "label2"
anchors.centerIn: parent
}
}
}Keys.onSpacePressed: { console.log("Main::onSpacePressed") var localbuttons = [b1, b2] console.log(b1, localbuttons[0]) // QQuickRectangle(0x1d43b40) QQuickRectangle(0x1d43b40) b1.Keys.pressed(event) // OK localbuttons[0].Keys.pressed(event) // OK } property variant buttons: [] Component.onCompleted: buttons = [b1, b2] Keys.onEscapePressed: { console.log("Main::onEscapePressed") console.log(b1, buttons[0]) // QQuickRectangle(0x1d43b40) QQuickRectangle(0x1d43b40) b1.Keys.pressed(event) // OK buttons[0].Keys.pressed(event) // <-- Why here an error for Quick 1.1? For 2.0 is OK }
}
@
Example work correctly in Qt 5.2.1 QML 2.0 (also replaced "import QtQuick 1.1" to "import QtQuick 2.0"), but in Qt 5.2.1 QML 1.1 it doesn't. Other versions I didn't test.There is different behavior when I resend keyboard event from main element to subrectangles:
- when I access to element directly or via local array resending work (see onSpacePressed);
- when I store reference to element in property and use element via property, then resend doesn't work (see onEscapePressed).
For me is very import to use property as array to JS objects. Why is error in QML 1.1?
-
What happens when you change:
@
property variant buttons: []
@into:
@
property variant buttons: new Array()
Component.onCompleted: { buttons.push(b1); buttons.push(b2); }
@variant was in any case not perfect in QtQuick 1. It has been improved and replaced by "var" property in QtQuick 2.
-
"What happened when I change":http://i33.fastpic.ru/big/2014/0311/c2/eb294ca3677a15588659bc2072dc06c2.png
@property variant buttons: new Array()@
Error: Do not use 'Array' as a constructor. (M112)
-
It is not an error, but a warning ;) I have used this before, that is why I have proposed it as a solution.
-
Result is the same :(
bq. Starting C:\Qt\Qt5.2.1\5.2.1\mingw48_32\bin\qmlviewer.exe...
Qml debugging is enabled. Only use this in a safe environment!
Main::onEscapePressed
QDeclarativeRectangle(0x21ac900) undefined
Rectangle1::pressed
file:///D:/projects/Qt/QML/Test/Test.qml:34: TypeError: Result of expression 'buttons[0]' [undefined] is not an object.
C:\Qt\Qt5.2.1\5.2.1\mingw48_32\bin\qmlviewer.exe exited with code 0 -
I see. Are you forced to use QtQuick1? It is deprecated in Qt 5...
What about:
@
property variant buttons: [b1, b2]
@Maybe it is a bug in the old code path. You can also try with Qt 4.8.6. I am sure I did things like that in QtQuick1 and they worked.
-
bq. Are you forced to use QtQuick1? It is deprecated in Qt 5…
I have no final decision about Qt version. Target board will come soon and if it supports OpenGL then I'll use Qt 5.0. If no then Qt 4.8.
Still the same :( (even for Qt 4.8.2)
-
Hey,
@sierdzio: I couldn't manage to set or add a value to an property variant array, too. It seems to be read-only!? I was using Qt 5.2.1 and QtQuick 2.0.
@suslov.maxim: Maybe you could try to use a "list":http://qt-project.org/doc/qt-4.8/qml-list.html instead?
-
[quote author="onek24" date="1394532585"]
sierdzio: I couldn't manage to set or add a value to an property variant array, too. It seems to be read-only!? I was using Qt 5.2.1 and QtQuick 2.0.[/quote]To say that again: do not use "variant" in QtQuick 2. Use "var" instead.
I am absolutely certain I managed to make it work even in Qt 4.8, but - sorry guys - I don't remember exactly how.
-
[quote author="sierdzio" date="1394532880"][quote author="onek24" date="1394532585"]
sierdzio: I couldn't manage to set or add a value to an property variant array, too. It seems to be read-only!? I was using Qt 5.2.1 and QtQuick 2.0.[/quote]To say that again: do not use "variant" in QtQuick 2. Use "var" instead.
I am absolutely certain I managed to make it work even in Qt 4.8, but - sorry guys - I don't remember exactly how.[/quote]
I never use variant, i just tried to find a solution for suslov.maxim.
And i could only manage to read out the values and to transform the array into a string. -
OK, searching through my memory, this popped out:
@
property variant buttons: new Array()
Component.onCompleted: {
var tempArray = new Array();
tempArray.push(b1);
tempArray.push(b2);
buttons = tempArray;
}
@The array might be read-only, but maybe you can overwrite the whole thing.
-
Yeah, in fact i could override the hole thing, thats what i basically meant by transforming it into a string, but i really didnt thought about creating a temp array...where is my coffee? good job sierdzio.
@ property variant abc: ["1"]
function test(){
var array = abc
array.push("2")
abc = array
console.log(abc.valueOf())
}@
Works fine! -
var also isn't work:
@file:///D:/projects/Qt/QML/TestFocus1/TestFocus1.qml:34:14: Expected property type
property var buttons: [b1, b2]^ @
No error using list:
@import QtQuick 1.1
Rectangle {
width: 300; height: 250; focus: trueproperty list<Rectangle> buttons: [ Rectangle { id: b1; width: 100; height: 62; color: "lightblue" property alias text: label.text Keys.onPressed: console.log("Rectangle1::pressed") Text { id: label text: "label1" anchors.centerIn: parent } }, Rectangle { id: b2; width: 100; height: 62; color: "lightgreen" Keys.onPressed: console.log("Rectangle2::pressed") Text { text: "label2" anchors.centerIn: parent } } ] Row { id: row children: [b1, b2] } Keys.onEscapePressed: { console.log("Main::onEscapePressed") console.log(b1, buttons[0]) b1.Keys.pressed(event) buttons[0].Keys.pressed(event) buttons[0].color = "red" buttons[0].text = "blablabla" }
}
@But I have one problem. Quote from http://qt-project.org/doc/qt-4.8/qml-list.html :
bq. While the rects property can be reassigned to a different list value (including an empty list), its individual values cannot be modified
I build buttons in runtime using Qt.createComponent and component.createObject. This solution leads to another dead end (because list content can't be modified in runtime).
-
[quote author="sierdzio" date="1394533597"]OK, searching through my memory, this popped out:
@
property variant buttons: new Array()
Component.onCompleted: {
var tempArray = new Array();
tempArray.push(b1);
tempArray.push(b2);
buttons = tempArray;
}
@The array might be read-only, but maybe you can overwrite the whole thing.[/quote]
Doesn't work. I have still error:
bq. Starting C:\Qt\Qt5.2.1\5.2.1\mingw48_32\bin\qmlviewer.exe...
Qml debugging is enabled. Only use this in a safe environment!
Main::onEscapePressed
QDeclarativeRectangle(0x48c900) QDeclarativeRectangle(name = "")
Rectangle1::pressed
file:///D:/projects/Qt/QML/TestFocus1/TestFocus1.qml:160: TypeError: Result of expression 'buttons[0].Keys' [undefined] is not an object.
C:\Qt\Qt5.2.1\5.2.1\mingw48_32\bin\qmlviewer.exe exited with code 0For line:
@console.log(b1, buttons[0])@I have output
bq. QDeclarativeRectangle(0x48c900) QDeclarativeRectangle(name = "")
but both variables must give same output (here "QDeclarativeRectangle(0x48c900)" for "b1" and "QDeclarativeRectangle(name = "")" for buttons[0]). Why?
-
It looks like he can find that it is a Rectangle, but he is basically just creating a copy of it in the array, so you are trying to access the duplicated component which basically doesn't exist.
-
Ok, then maybe throw away the array, and just work on children of your Row? Like this:
@
Row {
id: myRow
Rectangle {
id: b1; width
// ...
Keys.onEscapePressed: {
myRow.children[0].Keys.pressed(event);
}
@ -
[quote author="sierdzio" date="1394535292"]Ok, then maybe throw away the array, and just work on children of your Row? Like this:
@
Row {
id: myRow
Rectangle {
id: b1; width
// ...
Keys.onEscapePressed: {
myRow.children[0].Keys.pressed(event);
}
@[/quote]see
bq. I build buttons in runtime using Qt.createComponent and component.createObject. This solution leads to another dead end (because list content can’t be modified in runtime).
In that case he has to iterate trough all children and check for a given characteristic like objectNames or custom properties.
-
[quote author="sierdzio" date="1394535292"]Ok, then maybe throw away the array, and just work on children of your Row?[/quote]
Hmm... It's interesting.
@import QtQuick 1.1
Rectangle {
width: 300
height: 250
focus: trueRow { id: container Rectangle { id: b1 width: 100 height: 62 color: "lightgreen" Keys.onPressed: console.log("Rectangle1::pressed") Text { text: "label1" anchors.centerIn: parent } } Rectangle { id: b2 width: 100 height: 62 color: "lightblue" Keys.onPressed: console.log("Rectangle2::pressed") Text { text: "label2" anchors.centerIn: parent } } } property alias buttons: container.children Keys.onEscapePressed: { console.log("Main::onEscapePressed") console.log(b1, buttons[0]) b1.Keys.pressed(event) buttons[0].Keys.pressed(event) }
}
@It works. Are children can be updated in runtime?
-
[quote author="onek24" date="1394535649"]In that case he has to iterate trough all children and check for a given characteristic like objectNames or custom properties.[/quote]
That is an inconvenience, but not a showstopper, as it seems ;)
-
I'm sorry guys. Can you answer the question: Are children can be updated in runtime?
UPDATE: Yes, using component.createObject ad stuff like that.
Because children can be updated in runtime I see this as solution. Yes, it's not ideal but it works. Thank you very much to all and especially to sierdzio!