Problems with Open-Source Downloads read https://www.qt.io/blog/problem-with-open-source-downloads and https://forum.qt.io/post/638946

[SOLVED] parameter in constructor of a custom qquickitem



  • Hello,

    I used :
    @qmlRegisterType<MyClass>("MyLib", 0,1, "MyClass");@
    to used my class as a custom item in qml.

    It works fine.

    But now i would like to use the same class but i want to pass parameter to the constructor of the class.
    How can i used the qmlRegisterType for this.

    Thanks

    matteli


  • Moderators

    Add a default value to that new parameter, so that QML engine can discard it when generating meta objects. When constructing the object by hand in JavaScript or C++, that parameter will still be available.



  • Thanks for attention.
    But i want a parameter in the qml instance of my class.
    I put a piece of my code illustring the problem.

    main.ccp
    @
    #include <QGuiApplication>
    #include "map.h"
    #include "model.h"
    #include <thread>
    #include "message.h"
    #include <QQuickView>

    int main(int argc, char *argv[])
    {
    unsigned int width = 1024;
    unsigned int height = 608;

    QGuiApplication app(argc, argv);
    
    Model model;
    model.moveToThread(&model);
    model.start();
    
    qmlRegisterType<Map>("Histemul", 0,1, "Map");
    
    QQuickView view;
    
    view.setSource(QUrl::fromLocalFile&#40;"ui.qml"&#41;);
    view.setClearBeforeRendering(false);
    
    view.show();
    
    
    return (app.exec());
    

    }
    @

    ui.qml
    @
    import QtQuick 2.0
    import Histemul 0.1

    Item {
    Map {
    fill: "land"
    ...
    }
    ...
    }
    @

    With that, there is no problem. But now i want to pass to the constructor of the class Map the object model and i want to access model in the object constructed in qml.


  • Moderators

    There is no mechanism in QML that I know of that would allow you to do that. You need to change your approach: for example, add a new Q_INVOKABLE method like "initialise()" to your c++ class, and then in QML call:
    @
    Map {
    Component.onCompleted: {
    initialise();
    }
    }
    @

    This will fill your object. Another approach would be to use a singleton and access it in the default constructor.


  • Moderators

    Or just use the Q_PROPERTY setter to adapt every time "fill" changes.



  • But in all your approch, the class Map can't access "model" object declared in the main function. When i changed the fill, i used setFill Q_PROPERTY but in this function, i need to acess to the "model" object.

    Before used the qquickitem, i have tried to use QQuickWindow::beforeRendering() signal to connect with the painting function but because of problem, i prefered used qquickitem.
    When i have tried this, my constructor was :
    @
    Map::Map(int width, int height, int initialBlock, const QUrl & source, Model & model): QQuickView(source) , mWidth(width), mHeight(height), mTopLeftBlock(initialBlock), mModel(model)
    @
    but the qquickitem needs a defaut constructor

    I tried the singleton but it doesn't seems to work.

    The only approch i see for the moment is to use a double signal/solt connected.
    One signal when i'm in the setFill function connected to a slot in my function in Model class and at the end of the function a signal connected to a slot to a function in the Map Class.



  • The double signal/slot will not work because i can't access the object Map instanced in the qml code.


  • Moderators

    [quote author="matteli" date="1357994339"]The double signal/slot will not work because i can't access the object Map instanced in the qml code.[/quote]

    You need to set object name:
    @
    // QML
    Map {
    objectName: "myName"
    }

    // C++
    parent->findChild("myName");
    @

    Why didn't the singleton work? You should make Model class into a singleton and then it would be available in every place that has it's header included.



  • Ah ok, i tried a singleton with the class Map.

    What do you think to use setContextProperty for exposing the model object to qml code ?


  • Moderators

    You can do that if you wish, too. I don't know your app, so I can't say if it's required. Sometimes it's enough just to have it in c++, sometimes it's needed in QML, too.



  • ok i resolve my problem. I give a solution for others which have this problem.

    Objective : Give access to a object (named : model) for a qquickitem (named : map).

    Problem : for using a class as a custom quickitem, you must used qmlRegisterType which only support defaut constructor for the class. There is no possible to give a reference to model during the construction of map in qml code.

    My solution according to sierdzio suggestion :

    main.cpp
    @
    #include <QGuiApplication>
    #include "map.h"
    #include "model.h"
    #include <thread>
    #include <QQuickView>

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

    Model model;
    model.moveToThread(&model);
    model.start();
    
    qmlRegisterType<Map>("MyLib", 0,1, "Map");
    
    QQuickView view;
    
    view.setSource(QUrl::fromLocalFile&#40;"ui.qml"&#41;&#41;;
    view.setClearBeforeRendering(false&#41;;
    
    /* After the construction of map in QML code, i continue the init here*/
    Map* map = rootQml->findChild<Map *>("map");
    map->init(model);
    
    view.show();
    
    return (app.exec&#40;&#41;&#41;;
    

    }

    @

    map.h
    @
    #ifndef MAP_H
    #define MAP_H
    #include "model.h"
    #include <QQuickItem>

    class Map : public QQuickItem
    {
    Q_OBJECT

    public:
    Map();
    ~Map();

    void init(Model &model);
    

    private:
    //members
    Model *mModel;

    //methods
    QSGNode *updatePaintNode(QSGNode * oldNode, UpdatePaintNodeData * updatePaintNodeData);
    

    };
    #endif // MAP_H
    @

    map.cpp
    @
    Map::Map()
    {
    setFlag(QQuickItem::ItemHasContents, true);
    }

    Map::~Map()
    {
    delete mModel;
    }

    void Map::init(Model &model)
    {
    mModel = &model;
    return;
    }
    @

    ui.qml
    @
    import QtQuick 2.0
    import MyLib 0.1
    Item {
    Map {
    id: map
    objectName: "map"
    }
    }
    @

    Thank you sierdzio


  • Moderators

    I'm happy you have found a solution. Please add [Solved] to the beginning of your topic's title. I've already tagged it as solved for you.


Log in to reply