ListView的itemAtIndex不返回索引处的项目

如何解决ListView的itemAtIndex不返回索引处的项目

假设我们有一个模型和两个视图。两个视图使用相同的模型。第二个视图中的项目必须与第一个视图中的相应项目具有相同的宽度。项目之间的宽度不是恒定的。两个视图之间的项目具有相同的索引。

下面的代码产生两个矩形的系列,其索引为文本。 view2中的矩形更窄:

import QtQuick 2.15

Rectangle {
    ListView {
        id: view1
        y: 0
        height: 50
        width: parent.width

        model: ts_model
        delegate: Rectangle {
            width: 60
            height: 50
            color: "black"
            Text {
                text: index
                color: "white"
            }
        }

        orientation: Qt.Horizontal
        layoutDirection: "LeftToRight"
        spacing: 5
    }

    ListView {
        id: view2
        y: 100
        height: 50
        width: parent.width

        model: ts_model
        delegate: Rectangle {
            color: "yellow"
            width: 50
            height: 50
            Text {
                text: index
            }
        }

        orientation: Qt.Horizontal
        layoutDirection: "LeftToRight"
        spacing: 5
    }
}

enter image description here

让我们尝试将view1中的矩形宽度绑定到view2中的矩形。我希望能够使用view1.itemAtIndex(index)语法做到这一点:

ListView {
        id: view2
        y: 100
        height: 50
        width: parent.width

        model: ts_model
        delegate: Rectangle {
            color: "yellow"
            width: view1.itemAtIndex(index).width
            height: 50
            Text {
                text: index
            }
        }
(... some more code ...)

不幸的是,这不起作用-我得到TypeError: Cannot read property 'width' of null,有趣的是仅对某些项目失败了:

enter image description here

我确认:

  1. 两个视图都显示相同数量的元素(相同的模型,没有过滤)
  2. 两者的索引都从0开始,一直上升到模型中的元素数减去1(如两张图片所示)
  3. 两个索引都是整数
  4. view1view2是同一个父母的孩子,我验证了他们在通过id寻址时可以看到对方

为什么不起作用?

解决方法

这个答案是错误的。它仅适用于所有元素均可见的列表。当代表进入/超出范围时,这会崩溃。

但是,要回答最初的问题-itemAtIndex始终不返回项目的原因是由于构造顺序,即调用该方法时index处的项目未完全构造。

正如JarMan所建议的,问题与view1的子代构造有关。通过一个简单的测试就可以看出这一点。我添加了一条消息来标识创建矩形的顺序:

// view1
delegate: Rectangle {
            width: 60
            height: 50
            color: "black"
            Text {
                text: index
                color: "white"
                Component.onCompleted: console.log("Rect1 " + index + " completed")
            }
        }
// view2
delegate: Rectangle {
                color: "yellow"
                width: view1.itemAtIndex(index).width
                height: 50
                Text {
                    text: index
                }
                Component.onCompleted: console.log("Rect2 " + index + " completed")
            }

哪个会产生以下输出:

qml: Rect2 0 completed
qml: Rect1 0 completed
file:///...: TypeError: Cannot read property 'width' of null
qml: Rect1 1 completed
qml: Rect1 2 completed
qml: Rect1 3 completed
qml: Rect1 4 completed
qml: Rect2 1 completed
qml: Rect2 2 completed
qml: Rect2 3 completed
qml: Rect2 4 completed
qml: Rect2 5 completed
qml: Rect2 6 completed
qml: Rect2 7 completed
qml: Rect2 8 completed
qml: Rect2 9 completed
file:///...: TypeError: Cannot read property 'width' of null
file:///...: TypeError: Cannot read property 'width' of null
file:///...: TypeError: Cannot read property 'width' of null
file:///...: TypeError: Cannot read property 'width' of null
file:///...: TypeError: Cannot read property 'width' of null
qml: Rect1 5 completed
qml: Rect1 6 completed
qml: Rect1 7 completed

很明显,view2中没有正确创建的矩形是在view1对应的矩形可用之前创建的。

创建动态对象here

一种解决方法是:1)将第二个视图保存到单独的QML文件中; 2)在完成根项后将其创建为子视图:

view2's QML file

import QtQuick 2.0

ListView {
    id: view2
    y: 100
    height: 50
    width: parent.width

    model: ts_model
    delegate: Rectangle {
        color: "yellow"
        width: view1.itemAtIndex(index).width
        height: 50
        Text {
            text: index
        }
    }

    orientation: Qt.Horizontal
    layoutDirection: "LeftToRight"
    spacing: 5
}

main file

import QtQuick 2.15

Rectangle {
    id: rect
    Component.onCompleted: {
        Qt.createComponent("view2.qml").createObject(rect)
    }

    ListView {
        id: view1
        y: 0
        height: 50
        width: parent.width

        model: ts_model
        delegate: Rectangle {
            width: 60
            height: 50
            color: "black"
            Text {
                text: index
                color: "white"
            }
        }

        orientation: Qt.Horizontal
        layoutDirection: "LeftToRight"
        spacing: 5
    }
}

哪个会产生所需的结果: correct result

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-