SCP3008
SCP3008

Reputation: 145

Import QML Components from Custom QML Library

I have created a library to store custom QML components that I am making for an application. I am using Pyside6 with python. This is what the basic directory looks like:

library
|    |__CustomComponents
|       |__Components1  
|          |__CustomComponent1.qml
|
|__test
   |__MainComponent
      |__main.py
      |__Main.qml

library and test are on the same level. I want to be able to access the CustomComponent1.qml file for use in the Main.qml, but how would I go about writing an import statement for that in Python? Also, to be able to import Components1 as a module, is the qmldir file all I need to have there? It would be neat if there is a command I can use to generate the files I need to make a module.

Edit: Possible to use QQuickView and QQmlApplicationEngine together?

view = QQuickView()
view.setResizeMode(QQuickView.SizeRootObjectToView);

newWidget = newWidget()
view.rootContext().setContextProperty("headerWidget", headerWidget)

qml_file = os.fspath(Path(__file__).resolve().parent / 'Main.qml')
view.setSource(QUrl.fromLocalFile(qml_file))
if view.status() == QQuickView.Error:
    sys.exit(-1)
view.show()

Upvotes: 1

Views: 2835

Answers (1)

eyllanesc
eyllanesc

Reputation: 243955

You have to use qmldir to indicate that there is a module in that folder and for it to be used it must be in the list of imports of the engine and for this you must use the addImportPath method.

├── library
│   └── CustomComponents
│       └── Components1
│           ├── CustomComponent1.qml
│           └── qmldir
└── test
    └── MainComponent
        ├── main.py
        └── main.qml

CustomComponent1.qml

import QtQuick

Rectangle{
    id: root
    width: 100
    height: 100
    color: "salmon"
}

qmldir

module Components1
CustomComponent1 CustomComponent1.qml

main.py

import os
from pathlib import Path
import sys

from PySide6.QtCore import QCoreApplication, Qt, QUrl
from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QQmlApplicationEngine

CURRENT_DIRECTORY = Path(__file__).resolve().parent

LIBRARY_DIR = CURRENT_DIRECTORY.parents[1] / "library" / "CustomComponents"


def main():
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()
    engine.addImportPath(os.fspath(LIBRARY_DIR))
    url = QUrl.fromLocalFile(os.fspath(CURRENT_DIRECTORY / "main.qml"))

    def handle_object_created(obj, obj_url):
        if obj is None and url == obj_url:
            QCoreApplication.exit(-1)

    engine.objectCreated.connect(
        handle_object_created, Qt.ConnectionType.QueuedConnection
    )

    engine.load(url)

    sys.exit(app.exec())


if __name__ == "__main__":
    main()

main.qml

import QtQuick
import QtQuick.Window

import Components1

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    CustomComponent1{

    }
}

QQuickView

In the case of QQuickView, it has an engine so you must use that one, so the changes are:

main.py

import os
from pathlib import Path
import sys

from PySide6.QtCore import QCoreApplication, Qt, QUrl
from PySide6.QtGui import QGuiApplication
from PySide6.QtQuick import QQuickView

CURRENT_DIRECTORY = Path(__file__).resolve().parent

LIBRARY_DIR = CURRENT_DIRECTORY.parents[1] / "library" / "CustomComponents"


def main():
    app = QGuiApplication(sys.argv)

    view = QQuickView()
    view.engine().addImportPath(os.fspath(LIBRARY_DIR))
    url = QUrl.fromLocalFile(os.fspath(CURRENT_DIRECTORY / "main.qml"))

    def handle_status_changed(status):
        if status == QQuickView.Error:
            QCoreApplication.exit(-1)

    view.statusChanged.connect(
        handle_status_changed, Qt.ConnectionType.QueuedConnection
    )

    view.setSource(url)
    view.show()

    sys.exit(app.exec())


if __name__ == "__main__":
    main()

main.qml

import QtQuick

import Components1

Rectangle {
    width: 640
    height: 480

    CustomComponent1{

    }
}

Upvotes: 4

Related Questions