ListElement 字段作为属性?

问题描述 投票:0回答:5

这是我的代码:

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
    }
}

这给了我错误:

ListElement: cannot use script for property value

我该怎么办?

qt qml
5个回答
25
投票

ListElement
字段不是传统意义上的 QML 属性,而是其父级
ListModel
中的角色。所以属性绑定在这种情况下不起作用。这就是为什么你会收到 QML 错误:“ListElement:无法使用脚本作为属性值”,这有点令人困惑。

尽管已向 Qt 团队提交了修复此问题的请求,但迄今为止尚未实施任何解决方案。

同时,如果您不想实现自己的 C++ 类来处理列表模型,正如 @Luca Carlon 所建议的那样,我已经尝试过一种有效的 QML 解决方法/解决方案。要点是:

  • 当其字段需要引用其他属性时,请勿使用
    ListModel
  • 相反,使用
    ListModel.append()
    进行模型初始化,并使用
    ListModel.setProperty()
    进行模型更新。在这两个方法调用的参数列表中,可以将角色分配给其他属性,这相当于属性绑定。

将此 QML 解决方法/解决方案应用于原始示例代码将产生以下修改后的示例代码:

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);
        }
    }
}

如果您运行上述修改后的示例代码(例如使用 Qt 5.5.0),您将不再收到 QML 错误。当然,我也不喜欢这个 QML 解决方法/解决方案。


5
投票

我也遇到这个问题了。考虑采用此处报告的解决方案之一:https://bugreports.qt.io/browse/QTBUG-16289 根据您所解释的 Qt 版本。

我个人更喜欢用C++实现该模型。阅读此内容:http://cdumez.blogspot.com/2010/11/how-to-use-c-list-model-in-qml.html.


3
投票

我的解决方案是不使用

ListElement
作为模型项:

property real firstValue: 2
...

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

    ...
}

1
投票

如果您尝试从 C++ 引用未使用 Q_ENUM 注册的枚举,也可能会发生此错误。


0
投票

这也可能是另一种解决方法,因为“从 Qt 5.11 开始,ListElement 还允许将函数声明分配给角色。这允许使用可调用操作定义 ListElements。”

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
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.