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?


  • Moderators

    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)


  • Moderators

    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


  • Moderators

    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?


  • Moderators

    [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.


  • Moderators

    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: true

    property 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 0

    For 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.


  • Moderators

    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: true

    Row {
        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?


  • Moderators

    [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!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.