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

