1

I am writing some QML dialogs for an application front-end written in PySide6, and am unable to apply styling using the qtquickcontrols2.conf file specified in https://doc.qt.io/qt-6/qtquickcontrols-configuration.html.

However, the customised controls in the QML do not render using the style in qtquickcontrols2.conf and the message

qrc:/qt/qml/DialogButton.qml:12:17: QML Rectangle: The current style does not support customization of this control (property: "background" item: QQuickRectangle(0x1cc414e9560, parent=0x0, geometry=0,0 0x0)). Please customize a non-native style (such as Basic, Fusion, Material, etc). For more information, see: https://doc.qt.io/qt-6/qtquickcontrols2-customize.html#customization-reference

is output to the console upon rendering the dialog. Does anybody know how I can ensure that these resources are made available to QML or the QQmlApplicationEngine?

After creating a test project with just one dialog, this test loads the QML correctly using the QQmlApplicationEngine and I am able to retrieve the dialogs using the Qt Resource System, i.e.

def _loadQmlFile(self, qmlName: str) -> None:
        self._engine.load(QUrl(f"qrc:///qt/qml/{qmlName}.qml"))

in the DialogManager class, so the compiled resource file is being used to retrieve at least some of the QML resources.

The project uses setuptools and I am using the Qt Resource system to compile a .qrc file into Python with pyside6-rcc resources.qrc -o resources_rc.py and have tried moving this resource file into the directory containing the __main__.py file (recommended in Common resource file in PyQt/ PySide and resource file location) and moving that file outside of the main project directory, but the same error occurs and the dialog is not styled using the "Basic" style.

The directory structure is as follows:

|   pyproject.toml
|   resources.qrc
|   resources_rc.py
|   setup.cfg
|   setup.py
|
+---DialogTest
|   |   date_range_dialog.py
|   |   dialog_manager.py
|   |   resources_rc.py
|   |   __init__.py
|   |   __main__.py
|   |
\---QmlResources
        DateRangeDialog.qml
        DialogButton.qml
        qtquickcontrols2.conf

resources.qrc

<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/qt/qml">
    <file alias="qtquickcontrols2.conf">QmlResources/qtquickcontrols2.conf</file>
    <file alias="DateRangeDialog.qml">QmlResources/DateRangeDialog.qml</file>
    <file alias="DialogButton.qml">QmlResources/DialogButton.qml</file>
</qresource>
</RCC>

qtquickcontrols2.conf

Controls]
Style=Basic

[Basic]
Theme=Light
Accent=Blue

main.py

import sys

from PySide6.QtWidgets import QApplication

from DialogTest.dialog_manager import DialogManager

import DialogTest.resources_rc as resources_rc


def main() -> None:
    app = QApplication(sys.argv)

    dialogManager = DialogManager()
    dialogManager.loadDialog(
        name="DateRangeDialog",
        width=800, 
        height=180, 
        title="Enter Report Range",
        startDates=["14/08/23", "15/08/23"], 
        endDates=["15/08/23", "16/08/23", "17/08/23", "18/08/23"]
    )

    sys.exit(app.exec())


if __name__ == "__main__":
    main()

dialog_manager.py

from PySide6.QtCore import QObject, QStringListModel, QUrl
from PySide6.QtQml import QQmlApplicationEngine

from .date_range_dialog import DateRangeDialog


class DialogManager(QObject):
    _engine: QQmlApplicationEngine
    _dialog: DateRangeDialog

    def __init__(self):
        QObject.__init__(self)
        self._engine = QQmlApplicationEngine()

    def loadDialog(
            self,
            name: str,
            width: float,
            height: float,
            title: str,
            startDates: list[str],
            endDates: list[str]
    ):
        self.dialog = DateRangeDialog()
        self.dialog.width = width
        self.dialog.height = height
        self.dialog.title = title
        self.dialog.startDateModel = QStringListModel(startDates)
        self.dialog.endDateModel = QStringListModel(endDates)

        self._setRootContext(self.dialog)
        self._loadQmlFile(name)

        root = self._getQQmlEngineRoot()
        try: 
            root.outputDateRange.connect(self.dialog.outputDateRange)
        except AttributeError as e:
            print(e)

    def _setRootContext(self, dialog: DateRangeDialog):
        self._engine.rootContext().setContextProperty("dialog", dialog)

    def _loadQmlFile(self, qmlName: str) -> None:
        self._engine.load(QUrl(f"qrc:///qt/qml/{qmlName}.qml"))

    def _getQQmlEngineRoot(self) -> QObject:
        if not self._engine.rootObjects():
            raise AttributeError("Root objects for QQmlApplicationEngine not found")

        root = QObject()
        for rootObject in self._engine.rootObjects():
            if rootObject.inherits("QWindow"): 
                root = rootObject
                break

        return root
grahamhs
  • 11
  • 4

0 Answers0