【问题标题】:QML: calling itemAt on Repeater returns nullQML:在中继器上调用 itemAt 返回 null
【发布时间】:2016-09-29 11:03:38
【问题描述】:

我的代码:

import QtQuick 2.7
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480

    Column {
        Row {
            Repeater {
                id: rectRepeater
                model: 3
                Rectangle {
                    width: 30
                    height: 30
                    color: "red"
                    radius: 10
                }
            }
        }
        Row {
            Repeater {
                model: 3
                Text {
                    text: rectRepeater.itemAt(0).width;
                }
            }
        }
    }
}

我收到此错误消息:

TypeError: 无法读取 null 的属性“宽度”

我发现this post 说解决方案是像这样使用Component.onCompleted(只需在Text 对象中插入一个Component.onCompleted 处理程序):

import QtQuick 2.7
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480

    Column {
        Row {
            Repeater {
                id: rectRepeater
                model: 3
                Rectangle {
                    width: 30
                    height: 30
                    color: "red"
                    radius: 10
                }
            }
        }
        Row {
            Repeater {
                model: 3
                Text {
                    Component.onCompleted: {
                        text: rectRepeater.itemAt(0).width;
                    }
                }
            }
        }
    }
}

但这失败并出现同样的错误。

有什么想法吗?

【问题讨论】:

    标签: qt qml repeater


    【解决方案1】:

    当您调用itemAt(0) 时,rectRepeater 项目不会退出。

    rectRepeater 被实例化时,你应该调用itemAt

    Window {
        visible: true
        width: 640
        height: 480
        Column {
            Row {
                Repeater {
                    id: rectRepeater
                    model: 3
                    Rectangle {
                        width: 30
                        height: 30
                        color: "red"
                        radius: 10
                    }
    
                }
            }
            Row {
                Repeater {
                    id: textrep
                    model: 3
                    Text {
                        }
                }
            }
            Component.onCompleted: {
                //Here all object are instantiated
                for (var i = 0; i< textrep.count; i++){
                    textrep.itemAt(i).text = rectRepeater.itemAt(0).width
                }
            }
        }
    }
    

    【讨论】:

    • 谢谢,这行得通。所以关键是等待onCompleted。但是我自己的代码也在等待那个信号! (请参阅我的问题中的第二个代码 sn-p。)那么有什么区别?
    • 在您的代码中,onCompleted 信号仅适用于 Text 组件。所以它会在文本组件被实例化时发出。在我的代码中,onCompleted 应用于 Column 组件,当列组件和所有他的孩子被实例化时,它会发出。
    【解决方案2】:

    我会选择条件绑定

    Text {
        text: rectRepeater.count > 0 ? rectRepeater.itemAt(0).width : 0;
    }
    

    一旦 rectRepeater 实际上创建了至少一个委托,就会读取该委托的值。 即使 rectRepeater 的模型在某个时候再次变为空,或者索引 0 处的项目改变了它的宽度,这仍然有效

    【讨论】:

    • 酷,谢谢!这在某些方面比onCompleted 解决方案更优雅。你写了一些原因,它也让我在它影响的元素中拥有绑定代码,这非常好。一个缺点是它有点冗长(尤其是绑定不支持多语句绑定功能)并且很难理解它的目的,需要注释。但总而言之,这是我将使用的解决方案。请注意,Konstantin T. 的回答还允许通过分配 Qt.binding(...) 表达式对宽度进行动态绑定。
    • 嗯,我刚刚测试了多语句绑定函数,结果证明它们有效!这使您的解决方案更具吸引力。
    • 推测,未验证:这可能最终会设置文本 3 次(在此示例中),因为重复次数从 0 增加到 3。这里基本上无关紧要,但在其他一些情况下它可能足够重。
    • 当计数发生变化时,绑定表达式将再次被计算,但文本属性的设置器将意识到没有变化,因此不会对可视化或使用该文本的任何绑定进行不必要的更新请求属性作为其输入之一
    • 不确定多语句绑定是什么意思,但绑定表达式基本上是一个函数,可以任意复杂(并不是说这一定是个好主意)。您还可以在 rectRepeater 中定义一个函数来执行此操作并将该函数用作绑定表达式:text: rectRepeater.firstRectWidth()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-02
    • 1970-01-01
    • 2014-07-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多