简体   繁体   中英

QML Listview selected item highlight on click

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

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, eg 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

denoth提供的答案:您需要添加以下行:

listview1.currentIndex = index 

ListView provides so called " attached properties ", ie 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.

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

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

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!

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
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM