Friday, March 4, 2011

Creating custom ListView delegate in QML

Currently I am trying to port one of my application's view to QML. During porting activity I need to create custom ListView delegate. In any case it looks like in QML ListView dose not provide any default delegate so you need to create one.

So I wanted to put button on my every row of ListView and wanted to emit signal when that button is pressed.

Something like this.(This is final out put of my QML code)


So I began with simple ListView with basic delegate as shown in below code.

import Qt 4.7

Rectangle {
    width: 250
    height: 300

    Component {
        id: listDelegate
        Item {
        width: 250; height: 50
        
            Row {
             Column {
                 width: 200
                 Text { text: 'Name: ' + name }
                 Text { text: 'Cost:' + cost }
                }
            }
        }
    }

    ListModel {
             id: listModel

             ListElement {
                 name: "Apple"; cost: 2.45
             }
             ListElement {
                 name: "Banana"; cost: 1.95
             }
     }

    ListView {
          id: listView
          anchors.fill: parent; anchors.margins: 5
          model: listModel
          delegate: listDelegate
          focus: true
    }
}

Out put will look like below. In above code delegate is created to display one colum with two text element.



Now I need to add image in above item delegate which will act as button and will propogate click event with index of item being clicked.

To add image to item delegate I am adding another column to row element and adding image element in that, also handling various mouse event to simulate button.
Component {
             id: listDelegate

             Item {
                 width: 250; height: 50

                 Row {
                     Column {
                         width: 200
                         Text { text: 'Name: ' + name }
                         Text { text: 'Cost:' + cost }
                     }
                     Column {
                        width: 50
                        Image {
                          id: itemBtn
                          source: "btn1.png"
                          MouseArea {
                              anchors.fill: parent;
                              onEntered: {
                                  itemBtn.source= "btn2.png";
                              }

                              onExited: {
                                    itemBtn.source= "btn1.png";
                              }

                              onCanceled: {
                                    itemBtn.source= "btn1.png";
                              }

                              onClicked:{
                                  console.debug("clicked:"+ index);
                                  listView.currentIndex = index;
                              }
                          }
                       }
                    }
                }
             }
         }  

So it will look like below.

This is all. In case you want to add highlight to list then you can use following code. You need to add this code to Rectangle element of qml file. Please note that in above code, highlight only moves when you click button or you use keyboard arrow key.
Component {
          id: highlightBar
          Rectangle {
              width: 245; height: 40
              radius: 5
              color: "lightsteelblue"
              y: listView.currentItem.y;
              x: listView.currentItem.x-3;
              Behavior on y { PropertyAnimation {} }
          }
      }


And also you will need to change ListView element to set highlight like below.
ListView {
          id: listView
          anchors.fill: parent; anchors.margins: 5
          model: listModel
          delegate: listDelegate
          highlight: highlightBar
          highlightFollowsCurrentItem: false
          focus: true
    }

Thats all, hope this helps.

1 comment:

  1. i did this as delegate but it is not showing up

    Component {
    id: listDelegate

    Item {
    width: 250; height: 50

    Row {
    Column {
    width: 200
    Text { text: "Id: " + id + " , name:" + name + " ,cost:"+cost}
    }
    Column {
    width: 50
    Rectangle {
    id: itemBtn
    color:"yellow"
    MouseArea {
    anchors.fill: parent;
    onEntered: {
    itemBtn.color= "blue";
    }

    onExited: {
    itemBtn.color= "yellow";
    }

    onCanceled: {
    itemBtn.color= "yellow";
    }

    onClicked:{
    console.debug("clicked:"+ index);
    listView.currentIndex = index;
    }
    }
    }
    }
    }
    }
    }

    ReplyDelete