Magnus2552 Magnus2552 - 2 months ago 36
C++ Question

QML How to dynamically access ListView items

I have a ListView which has dynamically added Items, and what I kinda want to know is how I could access items for example by index. Specifically, I want to have the color of the item rectangle change when I change the color using the Color Dialog. I guessed it should be maybe possible to first set a variable to the current item before calling the color dialog and then in the onAccepted method change the color of that item using the variable, but I don't know how to achieve anything of this in QML, because I am rather new to QML. Maybe you can offer even a cleaner way to change the color of the item's rectangle when the color dialog was closed (onAccepted). Thx for any help! :)

import QtQuick 2.0
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Controls.Styles 1.4

Rectangle {
id: listViewContainer
width: parent.width/10*9;
height: 50
Behavior on height {
NumberAnimation {
duration: 100;
}
}

gradient: Gradient {
GradientStop {position: 0.0; color: "white" }
GradientStop {position: 1.0; color: "silver" }
}
radius: 5
ColorDialog {
id: colorDialog
title: "Please choose a color"
onAccepted: {
console.log("You chose: " + colorDialog.color)
Qt.quit()
}
onRejected: {
console.log("Canceled")
Qt.quit()
}
}

Component {
id: playerDelegate
Item {
anchors.left: parent.left
anchors.right: parent.right
height: 50
Column {
Text { text: '<b>Name:</b> ' + name }
Row {
MouseArea {
width: 20
height: 20
onClicked: {
colorDialog.visible = true;
playerColor = colorDialog.color;
//open color dialog
}

Rectangle {
radius: 3
anchors.fill: parent
color: playerColor
}
}
}
}
}
}

ListView {
id: playerListView
anchors.fill: parent
model:
ListModel {
id: playerListViewModel;
ListElement {
name: "Bill Smith"
playerColor: "red"
}
}
delegate: playerDelegate
}
Button {
id: addPlayerButton
anchors.top: playerListView.bottom
anchors.left: playerListView.left
anchors.right: playerListView.right
style: ButtonStyle {
label: Text {
text: "Add new player"
horizontalAlignment: Text.Center
}
}
onClicked: {
root.addnewPlayer(playerListView); //dont worry about this method
playerListViewModel.append({name: "Billy", playerColor: "blue"});
listViewContainer.height += 50;
}
}
}

Answer

There are many ways to do this..

One way might be like this:

You could add in a signal called colorChosen(var newColor) to that ColorDialog Item

Then, whenever the colorDialog is accepted, have it also send out that new signal.

Finally, connect that new signal from the colorDialog to your Player Delegate by using the connect() implementation

See added Comments and slight changes to your code for answers to your questions

  
 
      ColorDialog {
            id: colorDialog
       

            /*  Below the special signal you add to the color dialog
              which basically just sends out which color was 
              picked.      */

            signal colorChosen(var newColor)

            onAccepted: {
                 console.log("You chose: " + colorDialog.color)


                 /*  HERE IS how you actually send that signal out */
                              
                 colorChosen(colorDialog.color);
                
                 

            }
       
        }
 




 Component {
    id: playerDelegate
    Item {


        /*  where the colorDialog signal will be connected to 
             once it is created  below */

        function changeColor(newColor) { 

             /* HERE Is how you access a ListModel by index. */
             playerListViewModel.get(index).playerColor = newColor; 
             colorDialog.colorChosen.disconnect(changeColor);
        }



        anchors.left: parent.left
        anchors.right: parent.right
        height: 50
        Column {
            Text { text: '<b>Name:</b> ' + name }
            Row {
                MouseArea {
                    width: 20
                    height: 20
                    onClicked: {


                  /*  Below Is one way to connect it to the function 
                           to change the model                */

                        colorDialog.colorChosen.connect(changeColor);
                        colorDialog.visible = true;
                     
                    }



                    Rectangle {
                        radius: 3
                        anchors.fill: parent
                        color: playerColor
                    }
                }
            }
        }
    }
}

 

Comments