Place multiple items in one Cell in a GridView



  • Hi,

    is it possible to place multiple items in on Cell in a GridView? I'm using a QAbstractListModel to set the data.

    My Model:

    @
    /****************************************************************************
    **
    ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
    ** Contact: http://www.qt-project.org/legal
    **
    ** This file is part of the examples of the Qt Toolkit.
    **
    ** $QT_BEGIN_LICENSE:BSD$
    ** You may use this file under the terms of the BSD license as follows:
    **
    ** "Redistribution and use in source and binary forms, with or without
    ** modification, are permitted provided that the following conditions are
    ** met:
    ** * Redistributions of source code must retain the above copyright
    ** notice, this list of conditions and the following disclaimer.
    ** * Redistributions in binary form must reproduce the above copyright
    ** notice, this list of conditions and the following disclaimer in
    ** the documentation and/or other materials provided with the
    ** distribution.
    ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
    ** of its contributors may be used to endorse or promote products derived
    ** from this software without specific prior written permission.
    **
    **
    ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
    **
    ** $QT_END_LICENSE$
    **
    ****************************************************************************/
    #include <QAbstractListModel>
    #include <QStringList>

    //![0]
    class Timeline
    {
    public:
    Timeline(const QString &deviceImage, const QString &euro, const QString &kwh, const QString &time, const bool elementVisible);
    Timeline(const QString &date, const bool &elementVisible);
    Timeline(const bool &elementVisible);
    //![0]

    QString deviceImage() const;
    QString euro() const;
    QString kwh() const;
    QString time() const;
    QString date() const;
    bool elementVisible() const;
    

    private:
    QString m_deviceImage;
    QString m_euro;
    QString m_kwh;
    QString m_time;
    QString m_date;
    bool m_elementVisible;

    //![1]
    

    };

    class TimelineModel : public QAbstractListModel
    {
    Q_OBJECT
    public:
    enum TimelineRoles {
    DeviceImageRole = Qt::UserRole + 1,
    EuroRole,
    KwhRole,
    TimeRole,
    DateRole,
    ElementVisibleRole
    };

    TimelineModel(QObject *parent = 0);
    //![1]
    
    void addDevice(const Timeline &device);
    
    int rowCount(const QModelIndex & parent = QModelIndex()) const;
    
    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
    

    protected:
    QHash<int, QByteArray> roleNames() const;
    private:
    QList<Timeline> m_devices;
    //![2]
    };
    //![2]
    @

    My GridView:

    @
    import QtQuick 2.2
    import QtQuick.Layouts 1.1
    import QtQuick.Controls 1.1

    Rectangle {
    anchors.fill: parent

    GridView {
        id: gridView1
        anchors.fill: parent
        cellWidth: grid.width/3
        cellHeight: grid.height/3
        model: timelineModel
        delegate: Item {
            x: 5
            height: 50
            Column {
                spacing: 20
    
                Button { id: deviceImageButton; iconSource: deviceImage; visible: elementVisible; anchors.horizontalCenter: parent.horizontalCenter; onClicked: setVisibleEffect(euroText, kwhText, timeText) }
                Text { id: euroText; text: euro; font.pointSize: 12; visible: false; anchors.horizontalCenter: parent.horizontalCenter }
                Text { id: kwhText; text: kwh; visible: false; font.pointSize: 12; anchors.horizontalCenter: parent.horizontalCenter }
                Text { id: timeText; text: time; visible: false; font.pointSize: 12; anchors.horizontalCenter: parent.horizontalCenter }
    
                Rectangle {
                    id: dateRectangle
                    color: "#808080"
                    Text { id: dataText; text: date; visible: true; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: parent.horizontalCenter; }
                    //                    width: childrenRect.width
                    //                    height: childrenRect.height
                }
            }
        }
    }
    

    }
    @

    My first idea is to solve this with QList inside the TimelineModel? Or any other approaches?

    Cheers



  • Depends on what you want delegate can be what ever you want and derived from Item like Rectangle or whatever.



  • I want to place multiple buttons and text in one cell. How can I do this? Everytime if I place more than one button than the button gets in the next cell and not in the same cell.

    Any Ideas?



  • Do I have to modify my qml dynamically or can I handle this with my model?



  • Sorry i'm not really understand what you want or what's the problem. maybe this helps:

    @
    Rectangle {
    width: 300; height: 200

        GridView {
            id: grid
            anchors.fill: parent
            cellWidth: 80; cellHeight: 80
    
            model: ListModel {
    
              ListElement {
                  name: "Jim Williams"
                  portrait: "pics/portrait.png"
                  button_1: "1_1"
                  button_2: "1_2"
                  button_3: "2_3"
              }
              ListElement {
                  name: "John Brown"
                  portrait: "pics/portrait.png"
                  button_1: "2_1"
                  button_2: "2_2"
                  button_3: "2_3"
              }
              ListElement {
                  name: "Bill Smyth"
                  portrait: "pics/portrait.png"
                  button_1: "3_1"
                  button_2: "3_2"
                  button_3: "3_3"
              }
              ListElement {
                  name: "Sam Wise"
                  portrait: "pics/portrait.png"
                  button_1: "4_1"
                  button_2: "4_2"
                  button_3: "4_3"
              }
          }
            delegate: Item {
              width: grid.cellWidth; height: grid.cellHeight
              Column {
                  anchors.fill: parent
                  Image { source: portrait; anchors.horizontalCenter: parent.horizontalCenter }
                  Text { text: name; anchors.horizontalCenter: parent.horizontalCenter }
                  Button { text: button_1; onClicked: {console.log(button_1);}}
                  Button { text: button_2; onClicked: {console.log(button_2);}}
                  Button { text: button_3; onClicked: {console.log(button_3);}}
              }
          }
          highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
          focus: true
        }
    }
    

    @



  • But what is if you want to place in one cell for example 3 buttons and in the next cell for example 5 buttons... Can you handle this with your model oder do I have to change my qml every time dynamically?

    Thanks



  • The model never handle anything. You have dynamic data, so you need dynamic element creation. My source is only a solution if your model items have the same data structure. You see it, ListElement have always the same properties only the values are different. You are a German guy right?



  • Right! How can I use dynamic element creation? Is this possible with repeater?



  • Take a look in this forum or use "google":https://www.google.de/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=qml+dynamic+object+creation. And please add [SOLVED] to the titles of all your solved threads! I'm also from Germany :)



  • Thanks dasRicardo!

    I extend my code with a javascript to set my elements dynamically. But how can I set my button and my text in my gridview in one cell instead of placing them in separate cells?

    This is what I want:


    I Button I
    I Text I
    I Text I
    I Text I
    I
    I Button I
    I Text I
    I Text I
    I Text I

    This is how it looks like at the moment:


    I Button I I Button I
    I Text I I Text I
    I Text I I Text I
    I Text I I Text I


    my main.cpp

    @
    #include <QApplication>
    #include <QQmlApplicationEngine>
    #include <QtQml>
    #include <client.h>
    #include <timeline.h>

    #include <QQmlComponent>

    int main(int argc, char *argv[])
    {
    QApplication app(argc, argv);

    QQmlApplicationEngine engine;
    TimelineModel model;
    
    model.addDevice(Timeline("content/image/devices/water_heater.png", "1,70 €", "0,80 kWh", "16:00 - 16:45", true));
    model.addDevice(Timeline("content/image/devices/tv", "1,70 €", "0,80 kWh", "16:00 - 16:45", true));
                                                                                                             model.addDevice(Timeline("content/image/devices/device_placeholder.png", "1,70 €", "0,80 kWh", "16:00 - 16:45", true));
    model.addDevice(Timeline("12 August", false));
    

    engine.rootContext()->setContextProperty("timelineModel", &model); engine.load(QUrl(QStringLiteral("qrc:///main.qml")));

    return app.exec&#40;&#41;;
    

    }
    @

    my timeline.qml:

    @
    import QtQuick 2.2
    import QtQuick.Dialogs 1.1
    import QtQuick.Controls 1.1
    import "componentCreation.js" as MyScript

    Rectangle {
    id: timelineRectangle
    anchors.fill: parent
    visible: true
    Loader {
    id: qmlloader
    // anchors.fill: parent
    z: 1
    }

    Rectangle {
        id: rectangle1
        x: parent.width/2 - 10;
        width: 20
        height: parent.height;
        color: "#000000"
        clip: false
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.bottom: parent.bottom
        anchors.top: parent.top
    }
    
    Component {
        id: timelineDelegate
        Item {
            width: grid.cellWidth; height: grid.cellHeight
    
            Column {
                id: timelineColumn
                anchors.fill: parent
                spacing: 20
    
                Component.onCompleted: MyScript.createSpriteObjects(timelineColumn&#41;;
    
            }
        }
    }
    
    GridView {
        id: grid
        flickableDirection: Flickable.AutoFlickDirection
    
        anchors.fill: parent
        cellWidth: grid.width/3
        cellHeight: grid.height/3
        anchors.margins: 100
    
        delegate: timelineDelegate
        model: timelineModel
    }
    

    }
    @

    my componentCreation.js:

    @
    var component;
    var sprite;

    function createSpriteObjects(timeParent) {
    component = Qt.createComponent("TimelineItems.qml");
    if (component.status == Component.Ready) {
    sprite = component.createObject(timeParent);
    }

    if (sprite == null) {
        // Error Handling
        console.log("Error creating object");
        console.log("component: " + component.error);
    }
    

    }
    @

    my TimelineItems.qml

    @
    Rectangle {

    Column {
    
    
        Button {text: "Button"; anchors.horizontalCenter: parent.horizontalCenter}
        Text {text: "euro" }
        Text {text: "kwh" }
        Text {text: "time" }
    }
    

    }

    @


Log in to reply
 

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