Qt Quick ListView access to delegate item



  • Hello,
    i want to write a timer application with QuickControls and QML, the user should be able to add dynamic Start Times. I use a ListView, where the User can append TextFields with the Start Time. How can I get the values of the dynamic created TextFields, so i can use them to control my timer for example the Values from the TextField with the id textMin from the code below?
    Or is there a better way to do this?

    Thanks in advance

    import QtQuick 2.7
    import QtQuick.Controls 2.0
    import QtQuick.Layouts 1.3
    
    ApplicationWindow {
        visible: true
        width: 640
        height: 480
        title: qsTr("Listview")
        property int number: 0
    
        RowLayout{
        id:row
            Button {
                id: button1
                text: qsTr("Create Textfield")
                width: (parent.width / 5)*2
                height: 50
                onClicked: {
                    listModel.append({current: "text " + (++number)})
                }
            }
    
    
            Button {
                id: button2
                text: qsTr("Get Text")
                width: (parent.width / 5)*2
                height: 50
    
                onClicked: {
                    //get the Text from the Textfield with textMin
                    //not working?
                    console.log(listView1.childAt(1).textMin.text)
                }
            }
        }
    
        ListView {
            id: listView1
            anchors.top: row.bottom
            anchors.bottom: parent.bottom
            anchors.left: parent.left
            anchors.right: parent.right
            delegate: Item {
                id: item
                anchors.left: parent.left
                anchors.right: parent.right
                height: 160
    
                ColumnLayout{
    
                    Label{
                        text:"Start-Time " + (index+1)
                    }
    
                    RowLayout{
                        Label{
                            text: "Min: "
                        }
    
                        TextField{
                            id: textMin
                        }
                    }
    
                    RowLayout{
    
                        Label{
                            text: "Sec: "
                        }
    
                        TextField{
                            id: textSec
                        }
                    }
                }
            }
    
            model: ListModel {
                id: listModel
            }
        }
    }
    


  • @ht1723 Delegate objects shouldn't usually be used from outside that object itself. You can add a button to the delegate and update the model with listModel.setProperty(index...) or do something else when it's clicked.

    In theory you can add to the delegate:

    Connections {
                    target: button2
                    onClicked: {
                        console.log("click received in", index)
                    }
                }
    

    but this works only if the proper delegate item is visible (i.e. inside the view area) at that moment, and all the visible delegate items will catch that signal. This is because the delegate items are created dynamically when the view sees it fit and usually it has only the visible items (plus couple of extra before and after) existing at each moment, and this is also the reason why you shouldn't access the delegate items from outer objects.

    However, the ListView has the currentItem property which keeps the current delegate item. You can set the currentIndex and then get the current item. In your example:

    Button {
                id: button1
                onClicked: {
                    listModel.append({current: "text " + (++number)})
                    listView1.currentIndex = listView1.count-1
                }
                //etc.
            }
    Button {
                id: button2
                onClicked: {
                    console.log(listView1.currentItem.text)
                }
                //etc.
            }
    delegate: Item {
                property alias text: textMin.text
                //etc.
    

    If you have only few items in the view you could also consider using a Repeater which has all the items existing all the time. There you can use itemAt(index).



  • Hi,
    thank you very much for your good answer,
    and for the hint with the repeater, i will look for a better way to display the Items.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.