QML 2D Array of rectangles; access via C++



  • Simple tasks: I have a 2D array of which each element represents the color of an rectangle. I want this to be displayd in QML. Here is the qml:

        Rectangle {
        Grid {
            Repeater {
                model: myModel
                Rectangle {
                    width: 50; height: 50
                    color: ColorRole
                }
            }
        }
    }
    

    The ColorRole was used by an QAbstractTableModel derived class. Unfortunately, this did not seem to be the right solution as it did not work out as expected. Any ideas?


  • Moderators

    Hi @wanderameise and Welcome to Qt Devnet,

    For C++ models to work with QML you need to define the rolesnames using roleNames() on C++ side and then you can use this role name string in QML. Some thing like:
    C++

    enum Role {
       ...
       ColorRole = Qt::UserRole+11
       ...
    }
    
    QHash<int, QByteArray> MyModel::roleNames() const
    {
        QHash<int, QByteArray> roles;
        roles[ColorRole] = "colorrole";
        return roles;
    }
    
    //Also re-implement data() as usual and return data for ColorRole
    

    QML

    Grid {
        anchors.fill: parent
        Repeater {
            model: myModel
            Rectangle {
                width: 50; height: 50
                color: model.colorrole //this corresponds to the string defined in roleNames()
            }
        }
    }
    
    


  • Thanks for the reply.

    Yes I did all that but I ran into the issue that QAbstractTableModel didn't do the trick since data() was only called for rows and not for columns...

    The main task here is to represent a lets say 8x8 array of rectangles. Each one with a custom color. This should be modeled with an appropriate C++ model. Which approach would you suggest?


  • Moderators

    @wanderameise
    Why would you require columns ? All the elements in Grid are assigned and index. You can use that to uniquely identify each element. QAbstractItemModel would suffice too.



  • ok, so how do I force the model to be of size 8x8? What I did in my derived class QAbstractTableModel:

    int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE
    {
        return 8;
    }
    
    int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE
    {
        return 8;
    }
    

    I thought this is where I define the size of the grid and hence both values (row and column) create the index?? And here I provide the data:

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE
    {
        if (!index.isValid() || role != ColorRole)
            return QVariant();
        // Here I want to use index.row() and index.column() to acces my internal 2D array m_arr[8][8]
    }
    

    I just want a representation of my 2D array m_arr[8][8] with a gridview of 8x8 where each item is a rectangle.

    QAbstractItemModel looked way to complcated....


  • Moderators

    @wanderameise
    You have used a Grid and Repeater in QML. Repeater just repeats the item and Grid adjusts them accordingly. It doesnot know which Item is present in which cell.
    All you have is the index(a sequence starting from 0) property which you can make use of. It should work. Since you have an array and this index you can find out the its position in the array.
    For eg:
    index = 1
    position in array = (0,1)

    how to get ?

    row = index/total items in array's row (8 in your case)
    row = 1/8 = 0

    col = index%total items in array's row (8 in your case)
    col = 1%8 = 1

    index = 11
    position in array = (1,3)

    Thus the above logic should work even without the need for column(Note: we dont need it because Repeater will refer to rows only)

    Now if you want to make use of columns then IMO you will need to use TableView instead of Grid and Repeater.



  • Yes, you talk about flattening the Matrix. Ok, that's one approach that could work.

    Maybe flattening might be the onyl solution since I have no idea hot to get TableView involved in this. It wants me to create TableViewColumns but the number of columns is decided dynamically and they dont have names or the meaning of a column in a table.

    Good Lord what a pain...

    Maybe the idea behind will bring some light into this: Just an array of rectangle which can be either black or white. It will be a game:

    link text

    (FYI, the engine in the background needs the information in a 2D array since it will perform some calculations on each item depending on its neighbors)


  • Moderators

    @wanderameise Grid + Repeater would be better option with "flattening" out the matrix. Emit dataChanged when required and return the updated data from data method.


Log in to reply
 

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