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

can't find my qmlRegisteredType on rootObject() children



  • Hi
    I am trying to cast qml Camera to QCamera for reading frames via QVideoProbe, for this, I registered the class and call the camera initialization method, which needs a QQmlApplicationEngine, to do this, I need to take Engine from the instance of the registered class, but I cannot find it among rootObjects, there is some snippets:

    QCamera initialisation:

    void ImageProvider::initCamera()
    {
        QObject *qmlCamera = engine->rootObjects().at(0)->findChild<QObject*>("qmlCam");
    
        camera = qvariant_cast<QCamera*>(qmlCamera->property("mediaObject"));
    
        connect(&probe,&QVideoProbe::videoFrameProbed,this,&ImageProvider::handleFrame);
        probe.setSource(camera);
    }
    

    main.cpp:

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include "QtAndroidTools.h"
    #include "imageprovider.h"
    Q_DECL_EXPORT int main(int argc, char *argv[])
    {
    #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    #endif
    
        QGuiApplication app(argc, argv);
        qmlRegisterType<ImageProvider>("com.myself", 1, 0, "Provider");
        QQmlApplicationEngine engine;
        const QUrl url(QStringLiteral("qrc:/main.qml"));
        QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                         &app, [url, &engine](QObject *obj, const QUrl &objUrl) {
            if (!obj && url == objUrl)
                QCoreApplication::exit(-1);
            ImageProvider *imageProvider = engine.rootContext()->findChild<ImageProvider *>("obj");
            qDebug()<<engine.rootObjects().at(0)->children();
            imageProvider->Init(&engine);
        }, Qt::QueuedConnection);
        engine.load(url);
    
        return app.exec();
    }
    

    main.qml

    import QtQuick 2.12
    import QtQuick.Controls 2.12
    import QtQuick.Window 2.12
    import QtQuick.Dialogs 1.3
    import com.myself 1.0
    ApplicationWindow {
        id: page
        visible: true
        width: 360
        height: 520
    
        Provider {
            id:obj
        }
        Component {
            id: mainPg
            BannerTest {}
        }
        StackView {
            id: stackView
            anchors.fill: parent
            initialItem: mainPg
        }
    
    }
    

    in general, I need my provider to be in BannerTest, since the camera is launched from there, but for now I need to at least understand how to find it in main

    qDebug()<<engine.rootObjects().at(0)->children(); output is (QQuickRootItem(0xdaa7e520), StackView_QMLTYPE_3(0xdf3a39a0))
    

    As you can see, there is no probider instance, can you tell me what i'm doing wrong?



  • @kshegunov
    Indeed, the further I dug into this problem, the more difficult it was to see the solution that lay on the surface, thank you all very much for your advice, it really helped to solve my problem.

    So, perhaps someone will be useful, the solution:
    in main.cpp:

            qmlRegisterType<ImageProvider>("com.myself", 1, 0, "Provider");
    

    in ImageProvider:

    void ImageProvider::initCamera()
    {
    
        QQmlEngine * contextEngine = QQmlEngine::contextForObject(this)->engine();
        QQmlApplicationEngine *engine = qobject_cast<QQmlApplicationEngine*>(contextEngine);
    
        QObject *qmlCamera = engine->rootObjects().at(0)->findChild<QObject*>("qmlCam");
        camera = qvariant_cast<QCamera*>(qmlCamera->property("mediaObject"));
    
        connect(&probe,&QVideoProbe::videoFrameProbed,this,&ImageProvider::handleFrame);
        probe.setSource(camera);
    }
    

    in qml:

        Provider {
            id: obj
            objectName: "object"
        }
            onClicked:{
                stackView.push("qrc:/PreviewScreen.qml")
                obj.initCamera()
            }
    

  • Moderators

    I really don't understand what you're attempting, to be honest. What is BannerTest and why should be there anything within it, as it appears empty?

    @Deymos said in can't find my qmlRegisteredType on rootObject() children:

    I need to take Engine from the instance of the registered class

    https://doc.qt.io/qt-5/qqmlengine.html#qmlEngine

    At any time for an object that's part of the QML/Quick tree.



  • @kshegunov
    I apologize, maybe I incorrectly expressed my question, in general I have an application essence of which to work with the camera and analyze a person in real time, for this in transition to the analysis page I need to enable the camera. if I initialize and run the camera in Main.qml when app is started, everything works fine, but if I need to initialize the camera later, when switching to the page, difficulties appear, since I need to read frames from the camera via QVideoProbe and transmit to OpenCV, it seems to me this option more efficient than capture 30 times per second, and for this I need to initialize and transfer the camera to the C ++ class when switching to a page with a camera, and here is the essence of my problem, I register the class in which the camera is transmitted, since QmlregisterType support only the standard constructor, I am looking for QML my registered class and trying to convey to him the correct Engine, but the problem is that through Findchild I can't find my registered class, and because of this, I can not call the transmission function of the Engine and therefore convey the camera in C ++ class, I hope this time it matched)

    I tried to create a camera in main.Qml and create VideoOutput already on the page where the camera should be, and i tried to specify the camera through the

    source: camera
    

    but it didn't work out, videoouutput is empty, but still it is not the best way, so the camera will be launched throughout the application and it will cause resource loss, it would be nice if you suggest ways to solve the first problem)



  • If the Provider is instantiated from QML then this should return what you want:

    qmlEngine(this)
    

    Otherwise it should return null.

    Provided by QQmlEngine header.



  • @fcarney
    As I understand you advise with qmlEngine(this) take Engine from qml instance of ImageProvider, but

     ImageProvider *imageProvider = engine.rootContext()->findChild<ImageProvider *>("obj");
    

    returns null, and I don't understand why, maybe I Incorrectly registering Provider, but it's

    qmlRegisterType<ImageProvider>("com.myself", 1, 0, "Provider");
    

    probably the right way to register components in qml.

    All I need to pass engine to Image provider for cast Camera to QCamera when page with camera is opened and instance of Camera was created



  • @Deymos said in can't find my qmlRegisteredType on rootObject() children:

    ImageProvider *imageProvider = engine.rootContext()->findChild<ImageProvider *>("obj");

    "obj" is the id, not the objectName.

    For your problem it would be better if the object used qmlEngine in an init routine called from qml.


  • Moderators

    @Deymos said in can't find my qmlRegisteredType on rootObject() children:

    As I understand you advise with qmlEngine(this) take Engine from qml instance of ImageProvider, but
    ImageProvider *imageProvider = engine.rootContext()->findChild<ImageProvider *>("obj");

    Yes, but I don't understand why the whole of shenanigans with findChild? Since this is your class define a couple of properties and methods and call them as appropriate from QML.

    returns null, and I don't understand why, maybe I Incorrectly registering Provider, but it's [...]

    For Qt5, this is the correct way.



  • @kshegunov
    Indeed, the further I dug into this problem, the more difficult it was to see the solution that lay on the surface, thank you all very much for your advice, it really helped to solve my problem.

    So, perhaps someone will be useful, the solution:
    in main.cpp:

            qmlRegisterType<ImageProvider>("com.myself", 1, 0, "Provider");
    

    in ImageProvider:

    void ImageProvider::initCamera()
    {
    
        QQmlEngine * contextEngine = QQmlEngine::contextForObject(this)->engine();
        QQmlApplicationEngine *engine = qobject_cast<QQmlApplicationEngine*>(contextEngine);
    
        QObject *qmlCamera = engine->rootObjects().at(0)->findChild<QObject*>("qmlCam");
        camera = qvariant_cast<QCamera*>(qmlCamera->property("mediaObject"));
    
        connect(&probe,&QVideoProbe::videoFrameProbed,this,&ImageProvider::handleFrame);
        probe.setSource(camera);
    }
    

    in qml:

        Provider {
            id: obj
            objectName: "object"
        }
            onClicked:{
                stackView.push("qrc:/PreviewScreen.qml")
                obj.initCamera()
            }
    

  • Moderators

    Why not have a camera property that you bind to? That's what I'd've done. In the setCamera method in C++ you can catch the pointer and connect your stuff. I continue to think that all this findChild is unnecessary, not to mention slow.



  • @kshegunov
    Yes, indeed, it makes sense, thanks :)


Log in to reply