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

Howto reset QML interface



  • Initially I used this approach for resetting my model every time somethings changed in class1.

    Class class1: public QObject{
    .
    .
    private:
    QQmlApplicationEngine mEngine;
    void resetModel ( );
    }
    
    class1::resetModel ( ) {
        mEngine.rootContext()->setContextProperty("class1ExposedObj", this);
    }
    

    This approach works fine for me but now I've another class, say class2 which also needs to be exposed to QML. So I thought I should put mEngine in my main.cpp and define resetModel() outside class.

    void resetModel(QQmlApplicationEngine &mEngine ,QList<QObject *> myObjects){
      
        mEngine.rootContext()->setContextProperty("class1",myObjects[1]);
        mEngine.rootContext()->setContextProperty("class2",myObjects[2]);
        .
        .
        .
        mEngine.rootContext()->setContextProperty("classN",myObjects[n]);
    }
    

    Is their a better approach of resetModel() ?


  • Moderators

    @pingal said in Howto reset QML interface:

    Is their a better approach of resetModel() ?

    yes, use a proper c++ model, like a QAbstractListModel.

    The models have reset, and changed signals that the QML Views correctly react to


    The cheap way would be to make a parent "ContextPropertyClass" and add your QLists of QObject* as A QVariant property. Then an emit of your defined changed signals will cause a reevaluation of the property.


  • Moderators

    @pingal said in Howto reset QML interface:

    Initially I used this approach for resetting my model every time somethings changed in class1.

    what changes in your classes and how do you use them in QML?
    if you talk about properties of the object then you should add a NOTIFY signal to all your objects properties and trigger it instead of setting the the whole object again.

    or if you would change the objects itself (new instance everytime) you could add a single wrapper object with a property containing all your object as a list object using QQmlListProperty and reset this list (clear and add objects again).



  • @J-Hilk :
    I would look into QAbstractListModel as you stated.

    @raven-worx :
    "if you would change the objects itself (new instance everytime) you could add a single wrapper object with a property containing all your object as a list object using QQmlListProperty and reset this list (clear and add objects again)"

    I'm exactly doing that. class1 is a wrapper actually, which notify (using QProperty) QML every time an object is modified/removed and it works.
    I read somewhere that resetting the view just require you to call setContextProperty for that corresponding instance as i have described in the above post i.e. resetModel() in class1.

    Now I need resetModel() to be placed such that when i call it, it should call setContextProperty for all objects, not just class1.


  • Moderators

    @pingal said in Howto reset QML interface:

    I'm exactly doing that. class1 is a wrapper actually, which notify (using QProperty) QML every time an object is modified/removed and it works

    and why do you want to reset the object again with setContextProperty ?!



  • @raven-worx : "why do you want to reset the object again with setContextProperty ?!"

    I think I've not clear the program structure clearly. I will explain it by an example.

    Lets say I've a CAR Class

    Class Car : public QObject {
    .
    Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged)
    .
    .
    attributes
    .
    }
    

    My objective was to list individual cars along with its attribute in my ListView. So I wrapped my CAR class with another class let say CarWrapper.

    Class CarWrapper : public QObject{
    
    Q_PROPERTY(QList<QObject*> myCar READ myCar WRITE setmyCar  NOTIFY myCarChanged)
    .
    .
    signals:
    void resetModel();
    
    public slots:
    void onAddCar(newCar);
    void RemoveCar(RemoveCarId);
    }
    
    void CarWrapper::resetModel()
    {
        mEngine.rootContext()->setContextProperty("CarWrapper", this);
    }
    

    PS: So every time CarWrapper::onAddCar() or CarWrapper::RemoveCar() is called, resetModel() is called within these functions to update the view


  • Moderators

    @pingal
    for exactly this case you should use QQmlListProperty



  • I will look into QQmlListProperty, But for now I've created ContextPropertyClass as below

    class ContextPropertyClass: public QObject{
    
    public:
        ContextPropertyClass(QObject *parent = nullptr);
        bool initialize();
        QList<QObject *> myObjects;
    
    public slots:
        void resetModel();
    
    private:
        QQmlApplicationEngine mEngine;
    
    };
    
    bool ContextPropertyClass::initialize(){
    
        resetModel();
        mEngine.load(QUrl(QStringLiteral("qrc:/mvc.qml")));
        if (mEngine.rootObjects().isEmpty())
            return false;
    
        return true;
    }
    
    
    void ContextPropertyClass::resetModel(){
    
        mEngine.rootContext()->setContextProperty("class1",myObjects[0]);
        mEngine.rootContext()->setContextProperty("class1",myObjects[1]);
    .
    .
    mEngine.rootContext()->setContextProperty("classN",myObjects[N]);
    }
    

    A temporary solution for now.

    Thanks for helpful suggestions.


  • Moderators

    @pingal
    i still dont get why you want to set the context properties over and over again when every property already has a notifier signal...



  • This post is deleted!


  • @raven-worx
    Q_PROPERTY will notify the view about the changes. At first I thought that my cpp logic can change the objects and in-order to reflect those changes in QML, I've to reset the ContextProperty() but now I understood, I don't need resetModel() at all as Q_PROPERTY notify signal will done this behind the scenes.

    Thanks


Log in to reply