[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:# 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)
# 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.