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

[PySide2 + QML] Error when registering a python class as QML type



  • Hi everyone,

    I'm trying to register my Python class as a QML type.
    This is the code I'm using:

    camera.py

    # This Python file uses the following encoding: utf-8
    from enum import Enum
    
    from PySide2.QtMultimedia import QCamera, QCameraImageCapture
    from PySide2.QtCore import QObject, QByteArray, Slot, Signal, Property
    
    
    class CameraMode(Enum):
        """Allowed camera modes.
    
        Modes represent a set of configurations used in particular scenarios.
        """
    
        PREVIEW = 0
        CAPTURE = 1
    
    
    class MyCamera(QObject):
        """Custom  camera controller class
    
        This class provides a wrapper around a QCamera instance that
        is used as the system camera."""
    
        cameraReady = Signal()
    
        def __init__(self):
            """Initialize the MyCamera instance."""
    
            QObject.__init__(self)
    
            camera_device = QByteArray(b"/dev/video2")
            self._camera = QCamera(camera_device)
            self._capture = QCameraImageCapture(self._camera)
    
            self._camera.statusChanged.connect(self._configure)
    
            self._camera.load()
    
        @Slot(QCamera.Status)
        def _configure(self, status):
    
            # Here we configure the camera
            if status == QCamera.LoadedStatus:
    
                encoding = self._capture.encodingSettings()
                encoding.setCodec("MJPEG")
                self.setMode(CameraMode.PREVIEW)
                self._camera.start()
    
            elif status == QCamera.ActiveStatus:
    
                self.cameraReady.emit()
    
            elif status == QCamera.Error:
    
                print("ERROR: {}".format(self._camera.errorString))
    
        def setMode(self, mode):
            """Switch the controlled camera to the desired resolution."""
    
            if not isinstance(mode, CameraMode):
    
                raise TypeError("mode should be of type CameraMode")
    
            if mode == CameraMode.PREVIEW:
    
                settings = self._camera.viewfinderSettings()
                settings.setResolution(1920, 1080)
    
            elif mode == CameraMode.CAPTURE:
    
                raise NotImplementedError
    
        def provideCamera(self, qml_camera):
            """Provide a new camera to a QDeclarativeCamera instance.
    
            This function is used to change the QCamera associated to a QML Camera
            in order to provide the configurations that are not allowed by the
            QML type.
            """
    
            qml_camera.setMediaObject(self._camera)
    
    

    man.py

    # This Python file uses the following encoding: utf-8
    
    # Stdlib imports
    import sys
    import os.path
    
    # Qt imports
    from PySide2.QtWidgets import QApplication
    from PySide2.QtQml import QQmlApplicationEngine, qmlRegisterType
    from PySide2.QtCore import QUrl
    
    # Our imports
    from camera import MyCamera
    
    
    if __name__ == "__main__":
        app = QApplication([])
        engine = QQmlApplicationEngine()
    
        # Expose MyCamera to QML
        qmlRegisterType(MyCamera, "Camera", 1, 0, "MyCamera")
    
        # Finally, we load the QML main file and launch the application
        engine.load(QUrl("qml/main.qml"))
    
        sys.exit(app.exec_())
    
    

    Howeven, when the code is run, i get the following error:

    QQmlApplicationEngine failed to load component
    ... main.qml:31 MyCamera is not a type
    

    I really don't see the problem, can anyone please help?

    Thanks in advance!



  • share main.qml and try changing:

    class MyCamera(QObject):
        """Custom  camera controller class
    
        This class provides a wrapper around a QCamera instance that
        is used as the system camera."""
    
        cameraReady = Signal()
    
        def __init__(self, parent=None):
            """Initialize the MyCamera instance."""
    
            QObject.__init__(self, parent)
    


  • Hi eyllanesc,

    thanks for your reply. I've tried your suggestion but I'm still getting the same error.
    Here's my main.qml source code:

    import QtQuick 2.14
    import QtQuick.Controls 2.14
    
    ApplicationWindow {
    
        id: root
    
        title: "QCamera Test"
        visible: true
        visibility: "FullScreen"
    
        Item {
    
            id: quit_handler
    
            focus: true
            Keys.onPressed: {
    
                // CTRL-Q quits the application
                if (event.key === Qt.Key_Q) {
    
                    event.accepted = true
                    Qt.quit()
    
                }
    
            }
    
        }
    
        MyCamera {
    
            onCameraReady: {
    
                content_loader.source = "CameraScreen.qml";
                provideCamera(content_loader.item.camera)
    
            }
    
        }
    
        // Used to dinamically change the application window content
        Loader {
    
            id: content_loader
    
            width: parent.width
            height: parent.height
    
            active: true
            visible: true
    
            source: "LoadingScreen.qml"
    
        }
    
    }
    


  • @NoodlesDev You have registered the class "MyCamera" in the module "Camera 1.0" but you have not imported it in the .qml, the solution is:

    import QtQuick 2.14
    import QtQuick.Controls 2.14
    
    import Camera 1.0
    
    ApplicationWindow {
    
        // ...
    


  • Thank you again @eyllanesc ! It worked!

    I had already tried doing so, but QtCreator showed an error in the main.qml file saying

     "QML module not found (Camera)"
    

    soo I guessed the import was not necessary! My bad.

    The initial error now is gone, but I'm still not managing to make my custom QML type work as expected: when I try to call the provideCamera() method:

       MyCamera {
    
            onCameraReady: {
    
                content_loader.source = "CameraScreen.qml";
                provideCamera(content_loader.item.camera)
    
            }
    
        }
    

    I get

    ReferenceError: provideCamera is not defined
    

    If I change it to:

       MyCamera {
    
            onCameraReady: {
    
                content_loader.source = "CameraScreen.qml";
                this.provideCamera(content_loader.item.camera)
    
            }
    
        }
    

    I get:

    TypeError: Property 'provideCamera' of object MyCamera(0x556bfff82130) is not a function
    

    I'm quite confused...



  • @NoodlesDev 1) Qt Creator has many disadvantages with PySide2 compatibility and among them they are not notified of registered types: Qt Quick Designer is not completely PySide2 compatible 2) Only qt-slots are visible from QML.

    @Slot(QObject) 
    def provideCamera(self, qml_camera):
        # ...
    


  • @eyllanesc once again, thanks a lot, your suggestion solved the issue.
    I guess I trusted Qt Creator too much.


Log in to reply