Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Q_RETURN_ARG and QQmlComponent - component not ready

I have spend 3 days carefully checking the best reference material I could find on internet about Q_RETURN_ARG. I have already included QQmlComponent. When using it on C++ to send a variable to display on QML, things are not always as they seems. Maybe because Qt5 is relatively new, there is not much material put together that we can rely on yet.

Basically, the code compiles without problem. When I ask it to run, it renders the qml page to the device with no problem, and then it gets the error:

QQmlComponent: Component is not ready
main.cpp:33 (int main(int, char**)): Got QML return: ""

Besides the files invoke.pro and myapplication.cpp, here are the key parts of the small example I am trying to work out, based on this post, Qt5 documentation,ICS tutorial, post, and link:

./myapplication.h

#include <QObject>
#include <QDebug>
#include <QQmlComponent>

class MyApplication : public QObject
{   Q_OBJECT
    public:
        explicit MyApplication(QObject *parent = 0);
        ~MyApplication(void) {}    
        QObject *object;
        QQmlComponent *component;

        void loadComponent(void)
        {   QQmlEngine engine;
            QQmlComponent *component = new QQmlComponent(&engine);
            component->loadUrl(QStringLiteral("qml/invoke/main.qml"));

            if(!component->isReady()){
                qWarning("qPrintable: %s", qPrintable(component->errorString()));
            }

            if (component->isLoading()){
                cout <<"==== component->isLoading ====";
                QObject::connect(component,
                                 SIGNAL(statusChanged()),
                                 this,
                                 SLOT(continueLoading()));
            }
            else{
                cout <<"==== component is not Loading ====";
                continueLoading();
            }
        }    
    signals:

    public slots:
        void continueLoading()
        {   QQmlEngine engine;
            QQmlComponent *component = new QQmlComponent(&engine);
            component->loadUrl(QStringLiteral("qml/invoke/main.qml"));

            if (component->isError()) {
                qWarning() << "component->isError()="<< component->errors();
            } else {
                object = component->create();
                cout <<"object created";
            }
        }    
};

./main.qml

import QtQuick 2.0
Rectangle {
    width: 360
   height: 360
    Item {
        function myQmlFunction(msg_cpp) {
            console.log("Got msg_cpp:", msg_cpp)
            return "output"
        }
    }
}

./main.cpp

#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
#include <QtQuick/QQuickItem>
#include <QtQuick/QQuickView>
#include <QQmlEngine>
#include <QtQml>
#include <QDeclarativeEngine>
#include <QtCore>
#include <QtQuick/QtQuick>
#include <QQmlComponent>
#include <QtQml/qqml.h>
#include "myapplication.h"

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

    QtQuick2ApplicationViewer viewer;
    viewer.setMainQmlFile(QStringLiteral("qml/invoke/main.qml"));

    MyApplication *myClass = new MyApplication();
    myClass->loadComponent();

    QObject *object=myClass->object;

    QVariant returnedValue;
    QVariant msg_cpp = "C++ message";
    QMetaObject::invokeMethod(object,
                              "myQmlFunction",
                              Q_RETURN_ARG(QVariant, returnedValue),
                              Q_ARG(QVariant, msg_cpp));
    qDebug() << "Got QML return:" << returnedValue.toString();

    viewer.showExpanded();
    delete object;
    return app.exec();
}

Which gives the error:

loadComponent()): qPrintable: file://qml/invoke/main.qml:-1 File not found
continueLoading()): component->isError()= (file://qml/invoke/main.qml: File not found) 
main.cpp:36 (int main(int, char**)): Got QML return: "" 

I noticed that main.qml is meant to load on Android using "QtQuick2ApplicationViewer" instead of "QQmlEngine". Should the "QQmlEngine" not be used at all for loading main.qml in attempt to get Q_RETURN_ARG running - when dealing with Android, and therefore that is why "QQmlComponent component" is not loading? If I try to use " QtQuick2ApplicationViewer viewer" replacing "QQmlEngine engine" for "QQmlComponent component", it says: "no matchning function for call to QQmlComponent".

Any suggestions how to get QQmlComponent initialized, so Q_RETURN_ARG starts working? Thanks!

like image 629
Gerry Woodberg Avatar asked Jan 09 '14 03:01

Gerry Woodberg


1 Answers

I got a quick review of your code and got it working with a few changes, but it has some big(BIG!) QT/coding concepts missing.

Some of the key errors to get it working:

  • File error is just a matter of setting the file path properly.
  • Loading source needs time, not an eager sequence of not ready -> load again with other QQmlEngine. (this is not fixed in my code)
  • myQmlFunction needs to get upper in QML tree, or some other kind of reference help.
  • ...

Here you can take a look at full code.

http://pastebin.com/PRLBtKWU

I would recommend you to take a look at this book http://qmlbook.org/ and to practice with QT examples for your current QT version.

like image 113
kikeenrique Avatar answered Oct 06 '22 22:10

kikeenrique