Guillaume Slashy
Guillaume Slashy

Reputation: 3624

ListElement fields as properties?

Here is my code :

import QtQuick 1.0

ListModel {
    property real firstValue: 2
    property real secondValue: 3
    property real thirdValue: 1
    id: leftGrid
    ListElement {
        icon: "Images/1.png"
        value: leftGrid.firstValue
    }
    ListElement {
        icon: "2.png"
        value: -1
    }
    ListElement {
        icon: "3.png"
        value: leftGrid.secondValue
    }
    ListElement {
        icon: "4.png"
        value: leftGrid.thirdValue
    }
}

This gives me the error:

ListElement: cannot use script for property value

What should I do?

Upvotes: 20

Views: 21366

Answers (5)

EricoDeMecha
EricoDeMecha

Reputation: 11

This also could be another workaround since "Beginning with Qt 5.11 ListElement also allows assigning a function declaration to a role. This allows the definition of ListElements with callable actions."

import QtQuick

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")
    Rectangle {
        anchors.fill: parent

        ListModel {
            id: fruitModel
            property real appleValue: 2.45
            property real orangeValue: 3.25
            property real bananaValue: 1.95
            ListElement {
                name: "Apple"
                // cost: 2.45
                // cost: fluidModel.appleValue // Error: ListElement: cannot use script for property value
                cost: function(newCost = 2.45){// value 2.45 could be stored in a persistent setting
                    return (fruitModel.appleValue = newCost);
                }
            }
            ListElement {
                name: "Orange"
                // cost: 3.25
                // cost: fluidModel.orangeValue // Error: ListElement: cannot use script for property value
                cost: function(newCost = 3.25){
                    return (fruitModel.orangeValue = newCost);
                }
            }
            ListElement {
                name: "Banana"
                // cost: 1.95
                // cost: fluidModel.bananaValue // Error: ListElement: cannot use script for property value
                cost: function(newCost = 1.95){
                    return (fruitModel.bananaValue = newCost);
                }
            }
        }

        Component {
            id: fruitDelegate
            Row {
                spacing: 10
                Text { text: name }
                // Text { text: '$' + cost } // if value
                Text { text: '$' + cost() } // if function
            }
        }

        ListView {
            anchors.fill: parent
            model: fruitModel
            delegate: fruitDelegate
        }
    }
}

Upvotes: 1

GO.exe
GO.exe

Reputation: 724

My solution to this is not using ListElement as model item:

property real firstValue: 2
...

ComboBox
{
    model: [
        { text: firstValue, value: firstValue },
        { text: secondValue, value: secondValue },
        { text: thirdValue, value: thirdValue }
    ]

    ...
}

Upvotes: 3

Air In Day Vees
Air In Day Vees

Reputation: 66

This error can also occur if you try to reference an enum from C++ that is not registered with Q_ENUM.

Upvotes: 1

Luca Carlon
Luca Carlon

Reputation: 9976

I had this problem as well. Consider adopting one of the solutions reported in here: https://bugreports.qt.io/browse/QTBUG-16289 according to your version of Qt as explained.

I personally prefer to implement the model in C++. Read this: http://cdumez.blogspot.com/2010/11/how-to-use-c-list-model-in-qml.html.

Upvotes: 5

jonathanzh
jonathanzh

Reputation: 1444

The ListElement fields are not QML properties in the traditional sense, but rather the roles in its parent ListModel. So property binding does not work in this case. That is why you get QML error: "ListElement: cannot use script for property value", which is a bit confusing.

Although there has been a request submitted to the Qt Team to have this fixed, so far no resolution has been implemented.

In the meantime, if you do not want to implement your own C++ class to handle the list model, as suggested by @Luca Carlon, there is a QML workaround/solution I have tried which works. The main points are:

  • Do not use ListModel when its fields need to reference other properties.
  • Instead, use ListModel.append() for the model initialization, and use ListModel.setProperty() for the model updating. Inside the argument list of these 2 method calls, the roles can be assigned to the other properties, which is equivalent to property binding.

Applying this QML workaround/solution to your original example code will result in the following revised example code:

import QtQuick 2.0

Rectangle {
    width: 400
    height: 200

    ListModel {
        property real firstValue: 2
        property real secondValue: 3
        property real thirdValue: 1
        id: leftGrid

    // The commented-out code belowwon't work:
    // ListElement:Cannot use script for property value.
    //        ListElement {
    //            icon: "Images/1.png"
    //            value: leftGrid.firstValue
    //        }
    //        ListElement {
    //            icon: "2.png"
    //            value: -1
    //        }
    //        ListElement {
    //            icon: "3.png"
    //            value: leftGrid.secondValue
    //        }
    //        ListElement {
    //            icon: "4.png"
    //            value: leftGrid.thirdValue
    //        }
    // QML workaround/solution to the above code:

        // 1. Initialize the list model:
        property bool completed: false
        Component.onCompleted: {
            append({"icon": "Images/1.png", value: leftGrid.firstValue});
            append({"icon": "2.png", value: -1});
            append({"icon": "3.png", value: leftGrid.secondValue});
            append({"icon": "4.png", value: leftGrid.thirdValue});
            completed = true;
        }

        // 2. Update the list model:
        onFirstValueChanged: {
            if(completed) setProperty(0, "value", leftGrid.firstValue);
        }
        onSecondValueChanged: {
            if(completed) setProperty(2, "value", leftGrid.secondValue);
        }
        onThirdValueChanged: {
            if(completed) setProperty(3, "value", leftGrid.thirdValue);
        }
    }
}

If you run the above revised example code, using Qt 5.5.0 for example, you will no longer get the QML error. Sure, I do not like this QML workaround/solution either.

Upvotes: 26

Related Questions