You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PySide6中QtQuickControls无法加载qtquickcontrols2.conf样式问题

问题描述

我用PySide6开发QML对话框,无法通过qtquickcontrols2.conf文件应用样式。渲染对话框时控制台报错:

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).

测试项目可通过QQmlApplicationEngine加载QML,也能通过Qt资源系统获取资源,但对话框始终不应用“Basic”样式。项目使用setuptools,已通过pyside6-rcc resources.qrc -o resources_rc.py编译资源文件,调整文件位置后问题依旧。

项目目录结构

|   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

如何确保这些资源能被QML或QQmlApplicationEngine识别?


解决方案

1. 修正配置文件的资源路径

QtQuick Controls 2的qtquickcontrols2.conf必须放在资源根目录(/)下才能被自动读取,不能放在/qt/qml前缀下。修改resources.qrc拆分资源前缀:

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

重新编译资源文件到DialogTest目录:

pyside6-rcc resources.qrc -o DialogTest/resources_rc.py

2. 调整资源加载顺序

Qt会在QApplication实例化时读取配置文件,因此必须先加载资源再创建应用实例。修改__main__.py的导入顺序:

import sys
import DialogTest.resources_rc as resources_rc  # 移至最前,优先加载资源

from PySide6.QtWidgets import QApplication
from DialogTest.dialog_manager import DialogManager


def main() -> None:
    app = QApplication(sys.argv)
    # ... 后续代码不变

3. 验证样式加载状态

在main函数中添加代码,确认样式是否生效:

from PySide6.QtQuickControls2 import QQuickStyle
print("当前生效样式:", QQuickStyle.style())  # 应输出"Basic"

若输出不是Basic,说明配置文件未被读取,需检查资源路径和加载顺序。

4. 清理冗余资源文件

删除项目根目录下的resources_rc.py,仅保留DialogTest目录下的版本,避免资源加载冲突。

5. 检查QML中的硬编码样式

确保QML文件中没有指定原生样式(如style: NativeStyle),让配置文件的样式设置自动生效。


内容的提问来源于stack exchange,提问作者grahamhs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 05:40:15