Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Change a QML state from a model role



  • Hello, I'm fairly new to Qt/QML. My question is if it's possible to have a C++ model return a value that will change the state of a QML item. Something like:

    @
    Rectangle {
    id:myRect
    state:myRoleReturned
    states: [
    .
    .
    .
    ]
    }
    @

    In this simplistic example, I would like a model to return a value that will change the state of this rectangle. I tried returning a QString, but it says "Unable to assign [undefined] to QString"

    Any ideas would help!
    Thank you very much for your time



  • Try the following:

    1- Declare a C++ class (your model) that emits a signal each time the state of myRect needs to update. The new state can be the argument of the signal.

    2 - Use QQmlContext::setContextProperty(..) to make your C++ class "visible" in the QML world.

    3- Declare a QML Connections {...} component and attach the C++ signal that contains the new state to an javascript function that updates the state of myRect.

    I hope this helps!



  • Hello and welcome to devnet,

    yes it is possible to pass a string from Cpp to QML using a Model(It also works without a model), let me provide you an example:

    main.cpp
    @#include "Model.h"
    #include <QDeclarativeContext>
    #include <QDeclarativeView>
    #include <QApplication>

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

    QDeclarativeView *view = new QDeclarativeView;
    QDeclarativeContext *context = view->rootContext();
    QObject *object = (QObject *)view->rootObject();
    
    Model *model = new Model(0);
    
    view->setSource(QUrl("qrc:/qml/qmlview.qml"));
    context->setContextProperty("listModel", model);
    view->show();
    
    return a.exec&#40;&#41;;
    

    }@

    model.h
    @#ifndef MODEL_H
    #define MODEL_H

    #include <QModelIndex>

    class Model : public QAbstractListModel
    {
    Q_OBJECT
    public:
    Model(QObject *parent);
    ~Model();
    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    int columnCount(const QModelIndex &parent = QModelIndex()) const;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    enum Roles {
    NameRole = Qt::UserRole
    };
    QHash<int, QByteArray> roleNames() const {
    QHash<int ,QByteArray> roles;
    roles[NameRole] = "name";
    return roles;
    }
    };

    #endif // MODEL_H@

    model.cpp

    @#include "Model.h"

    Model::Model(QObject *parent)
    :QAbstractListModel(parent)
    {
    }

    int Model::rowCount(const QModelIndex &parent) const
    {
    return 4;
    }
    int Model::columnCount(const QModelIndex &parent) const
    {
    return 1;
    }
    QVariant Model::data(const QModelIndex &index, int role) const
    {
    if(role == NameRole)
    {
    return QString("Row%1, Column%2")
    .arg(index.row() + 1)
    .arg(index.column() +1);
    }
    return QVariant();
    }
    Model::~Model(){

    }@

    src.qrc
    @<RCC>
    <qresource prefix="/qml">
    <file>qmlview.qml</file>
    <file>image.bmp</file>
    </qresource>
    </RCC>@

    qmlview.qml
    @import QtQuick 1.1

    Rectangle {
    id: main
    height: 200; width: 200

    GridView {
        id: view
        width: 200; height: 200
    
        model: listModel
    
        delegate: Rectangle {
            height: 25
            width: 100
            Text { text: name }
        }
    }
    

    }@

    That way i pass 4 Strings to my QML file. The important part here is the data function, it returns the variable(QVariant) depending on the current index and role.

    There is also an easier way to provide a string from Cpp to QML.
    We will need an aditional setContextProperty in our main.cpp:

    @context->setContextProperty("myOwnCppText", QVariant("Yes it works"));@

    Let us just create a text in our QML-File:

    @ Text {
    width: 300; height: 20
    text: myOwnCppText
    }@

    It will display the text we pass from Cpp to QML. Another method would be to use the rootObject() and its setProperty() function. That way you just pass the name of the property as the first parameter and the value as the second one. Our QML-File should have included a property string variable, with the name of our first parameter:

    @ property string anotherTextFromCpp: ""
    Text {
    width: 300; height: 20
    text: anotherTextFromCpp
    }@

    A third method would be to invoke a QML method from Cpp and pass the text as a string as a parameter. Then we can handle the text in our function however we want/need.


Log in to reply