QML Listview selected item highlight on click
Asked Answered
E

7

35

Hi I want to put this code :

highlight: Rectangle {
    color: "black"
    radius: 5 
    opacity: 0.7
    focus: true
}

into mouseArea in onclick handler:

MouseArea {
    id: mouse_area1
    z: 1
    hoverEnabled: false
    anchors.fill: parent
    onClicked: {
    }

This is all listView:

ListView {
         id: listview1
         x: 0
         y: 82
        // width: 574
        // height: 967
         width: window.width
         height: window.height
         visible: true
         keyNavigationWraps: false
         boundsBehavior: Flickable.DragAndOvershootBounds
         opacity: 1
         maximumFlickVelocity: 2500
         anchors.leftMargin: 0
         highlightMoveSpeed: 489
         contentWidth: 0
         preferredHighlightEnd: 2
         spacing: 5
         highlightRangeMode: ListView.NoHighlightRange
         snapMode: ListView.SnapToItem
         anchors.bottomMargin: 0
         anchors.rightMargin: 0
         anchors.topMargin: 82
              anchors.fill: parent
              model: myModel
              delegate:Component {
                  //id: contactDelegate
                  Item {
                      property variant myData: model
                      width: 574; height: 90
                      Column {
                          x: 12
                          y: 0
                          width: 562
                          height: 90
                          anchors.rightMargin: 0
                          anchors.bottomMargin: 0
                          anchors.leftMargin: 12
                          anchors.topMargin: 0
                          anchors.fill: parent
                          spacing: 2
                          Text { text: '<b>ID: </b> ' + id_user ; verticalAlignment: Text.AlignTop; wrapMode: Text.NoWrap; horizontalAlignment: Text.AlignHCenter; color:"steelblue"; font.family: "Helvetica"; font.pointSize: 10 }
                          Text { text: '<b>Name: </b> ' + user_name; horizontalAlignment: Text.AlignHCenter; color:"steelblue"; font.family: "Helvetica"; font.pointSize: 10 }
                          Text { text: '<b>Lastname: </b> ' + user_lastname; horizontalAlignment: Text.AlignHCenter; color:"steelblue"; font.family: "Helvetica"; font.pointSize: 10 }
                          Text { height: 16; text: '<b>Tel number: </b> ' + user_number; verticalAlignment: Text.AlignVCenter; horizontalAlignment: Text.AlignHCenter; color:"steelblue"; font.family: "Helvetica"; font.pointSize: 10 }
                          Text { text: '<b>Address: </b> ' + user address; horizontalAlignment: Text.AlignHCenter; color:"steelblue"; font.family: "Helvetica"; font.pointSize: 10 }

                          MouseArea {
                              id: mouse_area1
                              z: 1
                              hoverEnabled: false
                              anchors.fill: parent
                              onClicked: 
                                  Item
                              {

                                }

                          }
                      }
                      }
              }

              //delegate: contactDelegate
              highlight: Rectangle
              {
                   color:"black"
                   radius: 5
                   opacity: 0.7
                   focus: true
              }
}

For now highlight is working only when using arrows, bbut this will be app for android so I need on touch that same effect, and SECOND question is how to read certain data from selected item in listview? Inside I have like id,name,lastname,number and adress. I want to put those values into text_input boxes.

Thank you

Evie answered 22/2, 2012 at 17:35 Comment(2)
I have found solution by myself: I needed to add this line: listview1.currentIndex = indexEvie
denoth: I've created your hint as an answer. This is better because everyone can see your question has been answered.Trigger
T
28

Answer provided by denoth: You need to add this line:

listview1.currentIndex = index 
Trigger answered 22/11, 2012 at 13:8 Comment(0)
O
40

It appears you need two solutions to your question:

  1. You want to be able to set the current item of the ListView when it's clicked
  2. You want to be able to know when the current selection changes

The Qt5 documentation says this about ListView mouse and touch handling:

The views handle dragging and flicking of their content, however they do not handle touch interaction with the individual delegates. In order for the delegates to react to touch input, e.g. to set the currentIndex, a MouseArea with the appropriate touch handling logic must be provided by the delegate.

Key input will work out-of-the-box but you'll need to explicitly catch the mouse/touch event on the delegate, and change the ListView.currentIndex value based on the index value of the selected delegate item.

Here's a full example:

import QtQuick 2.4
import QtQuick.Window 2.2

Window {
    width: 640
    height: 480
    visible: true

    ListModel {
        id: model
        ListElement {
            name:'abc'
            number:'123'
        }
        ListElement {
            name:'efg'
            number:'456'
        }
        ListElement {
            name:'xyz'
            number:'789'
        }
    }

    ListView {
        id: list
        anchors.fill: parent
        model: model
        delegate: Component {
            Item {
                width: parent.width
                height: 40
                Column {
                    Text { text: 'Name:' + name }
                    Text { text: 'Number:' + number }
                }
                MouseArea {
                    anchors.fill: parent
                    onClicked: list.currentIndex = index
                }
            }
        }
        highlight: Rectangle {
            color: 'grey'
            Text {
                anchors.centerIn: parent
                text: 'Hello ' + model.get(list.currentIndex).name
                color: 'white'
            }
        }
        focus: true
        onCurrentItemChanged: console.log(model.get(list.currentIndex).name + ' selected')
    }
}

It does the following things:

  • creates a simple list and model
  • uses a MouseArea item within the item delegate to update set the list.currentIndex = index which is a local var and unique to the selected item
  • listens for the onCurrentItemChanged event of the ListView to show how to access the current model item values
  • binds the text value of the currently selected item to the highlight item to show using the currently selected values elsewhere
Obscurant answered 27/2, 2015 at 1:21 Comment(0)
T
28

Answer provided by denoth: You need to add this line:

listview1.currentIndex = index 
Trigger answered 22/11, 2012 at 13:8 Comment(0)
K
5

ListView provides so called "attached properties", i.e. properties available in the delegate for the list. Among them Listview.view is a reference to the list itself. It can be used to access currentIndex property and update it. Hence, to solve your issue just:

  1. Uncomment //id: contactDelegate.
  2. Set contactDelegate.ListView.view.currentIndex = index in the OnClick even handler.
Khedive answered 7/8, 2013 at 9:23 Comment(0)
E
4

Simplest than ever, you can use: onCurrentItemChanged

ListView{
    id: listViewMainMenu
    signal Myselect(int playmode)
    onCurrentItemChanged: {
          Myselect(listViewMainMenu.currentIndex)
          console.log("index changed see this " + currentIndex)
    }
    // ...
}

// do not forget to connect to this signal otheritem.connect(thisitem.Myselect) //used in drag and works also with pathview

Elisa answered 17/9, 2014 at 22:27 Comment(1)
this is the easiest method, but it needs a little bit more description. The emitted signal has from the listview or pathview should be connected to a local function that changes the view. In Summary see this onCurrentItemChanged: Myselect(listViewMainMenu.currentIndex); console.log("index = " + currentIndex)Courtier
T
4

For those who use highlighting on a ListView with a specific height (being: not 100% height filled):

Be sure to enable the clip property of the ListView, as else the highlight will still be visible outside the ListView's borders while scrolling.

ListView 
{
    clip: true    
}   

As discussed here: Hide the highlight of a ListView while scrolling

Tyro answered 9/1, 2017 at 15:26 Comment(0)
C
0

The answer is indeed listView.currentIndex = index.

Whilst playing around with this answer, I found that the ListView may not have keyboard focus, so, I found it may be necessary to call listView.forceActiveFocus() so that up and down arrow key presses are handled.

I found the delegate, particularly the usage of Text in the ListView delegate to be verbose and cumbersome. To clean that up, I refactored an AppInfo component for rendering the contact in a nice manner.

To polish the answer, I provided some sample data for the contacts ListModel and cleaned up the highlight mechanism:

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
    ListView {
    id: listView
        anchors.fill: parent
        model: contacts
        clip: true
        focus: true
        delegate: Item {
            width: frame.width
            height: frame.height
            Frame {
                id: frame
                background: Item { }
                ColumnLayout {
                    id: columnLayout
                    AppInfo { label: "ID"; value:     id_user }
                    AppInfo { label: "Name"; value: user_name }
                    AppInfo { label: "Last Name"; value: user_lastname }
                    AppInfo { label: "Tel number"; value: user_number }
                    AppInfo { label: "Address"; value: user_address }
                }
            }
            MouseArea {
                anchors.fill: parent
                    onClicked: {
                        listView.currentIndex = index;
                        listView.forceActiveFocus();
                }
            }

        }
        highlight: Rectangle {
            border.color: "black"
            radius: 5 
            opacity: 0.7
            focus: true
        }
    }
    ListModel {
        id: contacts
        ListElement {
            id_user: "bgates"
            user_name: "Bill"
            user_lastname: "Gates"
            user_number: "555-Microsoft"
            user_address: "1 Microsoft Way"
        }
        ListElement {
            id_user: "sjobs"
            user_name: "Steve"
            user_lastname: "Jobs"
            user_number: "555-Apple"
            user_address: "1 Apple St"
        }
        ListElement {
            id_user: "jbezos"
            user_name: "Jeff"
            user_lastname: "Bezos"
            user_number: "555-Amazon"
            user_address: "1 Amazon Ave"
        }
    }
}

//AppInfo.qml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
RowLayout {
    property string label: "ID"
    property string value: "id"
    Text {
        Layout.preferredWidth: 100
        text: label
        verticalAlignment: Text.AlignTop
        wrapMode: Text.NoWrap
        horizontalAlignment: Text.AlignRight
        color: "steelblue"
        font.family: "Helvetica"
        font.pointSize: 10
        font.bold: true
    }
    Text {
        Layout.preferredWidth: 100
        text: value
        verticalAlignment: Text.AlignTop
        wrapMode: Text.NoWrap
        horizontalAlignment: Text.AlignLeft
        font.family: "Helvetica"
        font.pointSize: 10
    }
}

You can Try it Online!

Cheeky answered 20/10, 2022 at 6:7 Comment(0)
L
0

There's ItemDelegate since Qt 5.7. It reacts to mouse clicks by default.

import QtQuick
import QtQuick.Controls

ListView {
    model: ListModel {
        ListElement {
            name: "Item 1"
        }
        ListElement {
            name: "Item 2"
        }
        ListElement {
            name: "Item 3"
        }
    }
    delegate: ItemDelegate {
        text: name
    }
}
Lemieux answered 31/12, 2022 at 13:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.