QML中GridView按键导航时如何切换焦点并切换对应展示图片
问题原因及解决方案
核心错误点
- GridView层面的
Keys.onPressed事件中调用的modelData和image均不属于GridView的作用域,前者是委托(delegate)内的专属变量,后者是你拼写错误的委托内Image组件id,所以这行代码无实际效果 - 委托的焦点状态没有和GridView的
currentIndex联动,方向键切换只会修改currentIndex,不会自动修改对应委托的focus属性,因此你写的source三元绑定不会触发 GridView的currentIndex错误绑定了不存在的modelData.id,同时你给model属性绑定了无返回值的异步请求函数request(),属于冗余错误
修复步骤
- 删除GridView里无效的
Keys.onPressed事件,GridView自带的方向键导航本身就可以正常修改currentIndex,不需要额外写监听 - 给委托的
focus属性做绑定:focus: GridView.isCurrentItem,当该项为当前选中项时自动获得焦点,对应触发Image的source切换 - 删除GridView中错误的
currentIndex绑定,以及model: request()的绑定,异步请求的赋值逻辑已经在xhr回调中实现,初始值设为空数组即可 - 修正委托内的布局错误,你当前的矩形高度设置有重叠,可根据需求调整
修复后完整代码
import QtQuick 2.15 import QtQuick.Window 2.15 Window { width: 1920 height: 1080 visible: true title: qsTr("Hello World") Component.onCompleted: { mojgrid.focus = true request() // 页面加载完成后再发起请求 } function dobioResponseNapraviModel(response) { console.log("dobioResponseNapraviModel", typeof response) mojgrid.model=response } function request(){ console.log("BOK") const xhr=new XMLHttpRequest() const method="GET"; const url="http://api.themoviedb.org/4/list/1"; xhr.open(method, url, true); xhr.setRequestHeader( "Authorization", 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI5YjBkOGVlMGQzODdiNjdhYTY0ZjAzZDllODM5MmViMyIsInN1YiI6IjU2MjlmNDBlYzNhMzY4MWI1ZTAwMTkxMyIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.UxgW0dUhS62m41KjqEf35RWfpw4ghCbnSmSq4bsB32o'); xhr.onreadystatechange=function(){ if(xhr.readyState===XMLHttpRequest.DONE){ var status=xhr.status; if(status===0 || (status>=200 && status<400)){ dobioResponseNapraviModel(JSON.parse(xhr.responseText).results) }else{ console.log("There has been an error with the request", status, JSON.stringify(xhr.responseText)) } } } xhr.send(); } GridView { id:mojgrid anchors.fill: parent cellWidth: 350 // 和delegate宽度保持一致避免排版错位 cellHeight: 400 // 和delegate高度保持一致避免排版错位 model: [] // 初始设空数组,异步请求返回后再赋值 keyNavigationEnabled: true focus:true delegate: Rectangle{ id: rect; width: 350; height: 400; color:'gray'; focus: GridView.isCurrentItem // 核心绑定:当前选中项自动获得焦点 Image{ id:img; width:parent.width; height:parent.height-200 source:focus?"http://image.tmdb.org/t/p/w400"+modelData.poster_path : "http://image.tmdb.org/t/p/w400" + modelData.backdrop_path Rectangle{ id:rect2 width:parent.width height:text.height anchors.top:img.bottom color:'black' Text{ id:text text:modelData.title font.pointSize: 11 elide:Text.ElideNone color:'white' } } MouseArea{ id:mouse anchors.fill:parent onClicked: { mojgrid.currentIndex = index // 点击时修改GridView的currentIndex即可自动触发焦点变更 } } } Rectangle{ id:rect3 width:parent.width height:200 anchors.top:img.bottom color:'red' z:10 Text{ text:modelData.release_date anchors.left: parent.left anchors.top: parent.top color: 'white' } } } } }
补充说明
- 点击切换逻辑也同步做了优化,点击时直接修改GridView的
currentIndex即可自动触发对应委托的焦点变更,无需手动设置focus - 调整了GridView的cell宽高和委托宽高一致,避免出现排版错位问题
- 将request请求移到Component.onCompleted中触发,避免初始化时出现上下文错误
内容的提问来源于stack exchange,提问作者irena
相关产品推荐
相关产品推荐

