You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QML ListView的indexAt()函数始终返回-1的技术问题咨询

解决QML ListView indexAt()始终返回-1的问题

Hey there, let's dig into why your ListView's indexAt() keeps returning -1. I've run into this exact issue a few times with Qt QML, so here are the most common fixes and explanations:

1. You're using the wrong coordinate system

The indexAt(x, y) method expects coordinates relative to the ListView itself, not global screen coordinates. If you're passing screen-wide x/y values, that's almost certainly why you're getting -1.

For example, to target the top-left corner of the ListView's visible area (where the first item should be), use local coordinates like (1, 1) (avoiding the exact edge which might not register):

var firstVisibleIndex = id_conversation_list.indexAt(1, 1);

If you do need to use global screen coordinates, convert them to the ListView's local space first with mapFromGlobal():

// Let's say you have global screen coordinates (e.g., from a mouse event)
var globalX = mouseX;
var globalY = mouseY;
var localPos = id_conversation_list.mapFromGlobal(globalX, globalY);
var index = id_conversation_list.indexAt(localPos.x, localPos.y);

2. The ListView hasn't finished laying out items yet

If you're calling indexAt() too early (like in Component.onCompleted right after assigning the model), the ListView might not have rendered its items or finished calculating layouts yet.

Fix this by delaying the call until the ListView is ready. Use Qt.callLater() to let the event loop finish processing layout updates:

ListView {
    id: id_conversation_list
    anchors.fill: parent
    model: Conversations

    Component.onCompleted: {
        Qt.callLater(() => {
            var firstVisibleIndex = indexAt(1, 1);
            console.log("First visible index:", firstVisibleIndex);
        });
    }
}

Alternatively, you can listen to signals like onContentHeightChanged or onModelChanged to trigger your logic once items are loaded.

3. There are no visible items in the view

Double-check two things here:

  • Does your Conversations model actually have data? Print id_conversation_list.count to confirm.
  • Is the contentY (or contentX for horizontal lists) offset so far that no items are in the visible area? You can reset it to 0 temporarily to test.

4. Your delegate items have no size or are hidden

If your ListView's delegate has a height of 0, or its visible property is set to false, indexAt() won't detect it. Verify your delegate has explicit width/height values, or uses implicit sizing correctly.

5. Use visibleItems for a more reliable approach

If you just need the first visible item's index, skip indexAt() entirely and use the ListView's visibleItems property. This returns an array of all currently visible delegate items, so you can grab the first one directly:

var visibleItems = id_conversation_list.visibleItems;
if (visibleItems.length > 0) {
    var firstVisibleIndex = visibleItems[0].index;
    console.log("First visible index:", firstVisibleIndex);
}

This avoids coordinate-related issues entirely and is often more straightforward for this use case.

内容的提问来源于stack exchange,提问作者Swapnil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:44:16