Setting up a slot for QmlApplicationViewer



  • Hi there,

    I've been trying to find a solution for this the past few hours and I'm kind of stuck here. I have a main.cpp file which loads my qml file like this:

    @QmlApplicationViewer viewer;
    viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
    viewer.setMainQmlFile(QLatin1String("qml/test/main.qml"));
    viewer.showExpanded();@

    So nothing special. Also, I have a QThread that's running and which is emitting signals. Now I try to set up a slot (or something else) that calls a function in my qml file. I tried to add a slot into qmlapplicationviewer.h and implemented it in qmlapplicationviewer.cpp like that:

    @void QmlApplicationViewer::zoom(int scale){
    QVariant sc = scale;
    QObject* mainItem = this->findChild<QObject *>("mainItem");
    QMetaObject::invokeMethod(mainItem, "zoomIn", Q_ARG(QVariant, sc));
    }@

    In main.cpp I connect the signal to the slot:

    @QObject::connect( canThread, SIGNAL( zoom(int) ), &viewer, SLOT( zoom(int) ));@

    And this is my main.qml:

    @import QtQuick 1.1

    Rectangle{
    id: mainItem
    objectName: "mainItem"
    ...

    function zoomIn(steps) {
        bg.scale *= 2;
    }
    

    }@

    The signal is emitted correctly by my thread and also the slot gets called. Nevertheless, the function in qml is never executed

    I'm no real c++ crack so maybe someone can figure out where I run into problems.

    Thanks a lot!



  • Hello,

    May i ask you if :
    Did you have only one object of objectName: "mainItem" ?
    Did you check if mainItem is not null?



  • There is only one "mainItem", yes. But, the pointer "mainItem" in my slot is indeed 0. But why?



  • Try naming them differently, it will help the debugging process so you can examine them individually and have better clarity as to what you are looking at and what is causing the problem



  • I couldn't figure out how to solve this, so I made a little wordaround.

    I coded a parser class which takes the pointer from:

    @(QObject *)viewer.rootObject();@

    This works when putting all functions to your root object...



  • It seems to me that your solution is
    @
    QMetaObject::invokeMethod(
    (QObject *)viewer->rootObject(), // for this object we will call method
    "test" // name of the method to call
    // without parameters
    );
    @
    @
    PageStackWindow {
    id: mainApp
    ...
    function test() {
    myModel.test()
    }

    ListModel {
        id: myModel
        ...
        function test() {
            console.log("TEST OK");
        }
    }
    
    Page {
        ...
    }
    

    }
    @

    However, I am interested in more elegant solution.



  • OK, the reason for the problem is, that findChild() does not check "id", it looks for "objectName" property. Thanks to http://www.lothlorien.com/kf6gpe/?p=309 . Moreover, invokeMethod() should be called after setMainQmlFile() and must not be trigered from QML (i.e. qml calls C++ function which calls javascript function) before it finishes the initialization (not even from Component.onCompleted)

    @
    QMetaObject::invokeMethod(
    viewer->rootObject()->findChild<QObject *>("myModel"), // QML item
    "test" // method
    // parameters
    );
    @
    @
    PageStackWindow {
    id: mainApp
    ...

    ListModel {
        id: myModel
        objectName: myModel
        ...
        function test() {
            console.log("TEST OK");
        }
    }
     
    Page {
        ...
    }
    

    }
    @


Log in to reply
 

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