Get index of the delegate currently displayed - QML ListView

30,571

Solution 1

There are many ways to get the index of current item that is displayed in the screen. If you can get the x-y coordinate of current page, you can use indexAt method in ListView.

And in each delegate, you can find the index using index role within the scope of the delegate. The index is like a role you declared in your model, and is automatically assigned by ListView. For example,

ListView 
{
    delegate: Column
    {
        property int indexOfThisDelegate: index
        //...
    }
}

The index role is introduced here:

A special index role containing the index of the item in the model is also available to the delegate. Note this index is set to -1 if the item is removed from the model...

Another way is to explicitly assign value to the currentItem property in ListView, so the view can scroll by itself. Here is an simple example in Qt documentation, which is similar to your application.

Solution 2

I know this is quite old but I had the same problem and spend some time trying to find a way to get currentIndex that would work for me. In my case sometimes I need to change the width of my ListView so I have to recalculte currentIndex manualy every time I resize it.

But I found a highlightRangeMode property. When it's set to ListView.StrictlyEnforceRange then currentIndex is always updated automaticly and contains correct index of the currently visible item.

ListView {
    highlightRangeMode: ListView.StrictlyEnforceRange 
    // ...
}

Solution 3

You can do like that:

QModelIndex index =this->indexAt(event->pos());
        this ->setCurrentIndex(index);

Solution 4

You can use attached properties of ListView class (ListView). They are attached to each instance of the delegate.

See ListView.isCurrentItem or ListView.view example:


    ListView {
        width: 180; height: 200

        Component {
            id: contactsDelegate
            Rectangle {
                id: wrapper
                width: 180
                height: contactInfo.height
                color: ListView.isCurrentItem ? "black" : "red"
                Text {
                    id: contactInfo
                    text: name + ": " + number
                    color: wrapper.ListView.isCurrentItem ? "red" : "black"
                }
            }
        }

        model: ContactModel {}
        delegate: contactsDelegate
        focus: true
    }

Share:
30,571
marmistrz
Author by

marmistrz

Updated on July 05, 2022

Comments

  • marmistrz
    marmistrz almost 2 years

    I created a ListView, which displays a couple of pages of content defined by the user (plain text). The page displayed is a delegate. Only one page is visible at a time. I decided to use it to get snapping to one item, in the same way the iOS' launcher works. The user simply flicks between the pages. (this is to be used on touch screens)

    I need to have the index of the currently displayed page for some operation. currentIndex of the ListView always stays == 0. How can I get it?

    For those who prefer code:

     ListView
     {
          onCurrentIndexChanged: console.log(currentIndex) // this gets called only once - at startup
          delegate: Column
          {
               // The page displayed, only one page at a time
          }
     }
    

    Thanks

  • marmistrz
    marmistrz almost 10 years
    Even if I create the int property, I can do nothing with it because I can't programmatically read which page is that. I'll have to look into the two other options. And the ObjectModel example says nothing about currentItem
  • mcchu
    mcchu almost 10 years
    Oops, the last link does not contain complete codes. You can find the example code here.
  • marmistrz
    marmistrz almost 10 years
    Is there a way to find out the x,y in the content basing on the x,y in the window? I always know where in the window the current item is but I don't know how to find out x,y of the current page in the content (if I knew it, I could easily arithmetically calculate the current page (they're all the same size))
  • mcchu
    mcchu almost 10 years
    If your view displays only one delegate, you can try contentX and contentY properties of ListView, which is inherited from Flickable.
  • Andrew
    Andrew over 5 years
    Assigning a property works exactly as expected. In my case it came down to an obsessive need to be explicit with everything. Just writing "index" everywhere versus "itemId.currentIndex" made my eye twitch.