QML:在中继器上调用 itemAt 返回 null

Posted

技术标签:

【中文标题】QML:在中继器上调用 itemAt 返回 null【英文标题】:QML: calling itemAt on Repeater returns 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;
                    
                
            
        
    

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

有什么想法吗?

【问题讨论】:

【参考方案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()

以上是关于QML:在中继器上调用 itemAt 返回 null的主要内容,如果未能解决你的问题,请参考以下文章

QTableWidgetItem.itemAt(pos) 在 contextMenu 请求时总是返回 0

QTableWidget::itemAt() 返回看似随机的项目

滑块上的 QML 性能

列数可变的 QML 中继器和 QML 网格布局

qml 使用中继器从 Qlist 绘制折线图

具有“填充”过渡的 QML 中继器