python - PyQt 从不同目录导入 QML 主题
问题描述
我正在做一个 PyQt 项目。我想将主题放在与我的主 qml 不同的文件夹中,并允许潜在地加载不同的主题。我的目录设置如下图所示。如何引用主题中的属性?我计划最终使这个项目成为一个相当大的项目,因此希望有一个良好的目录结构来保持事物井井有条。目前我没有得到任何例外,但背景颜色与我的 Theme.qml 文件中的颜色不匹配。
main.qml
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12
import QtQuick.Window 2.12
import './Themes/'
ApplicationWindow
{
id: mainWindow
width: 640
height: 480
visible: true
color: Theme.primaryBackgroundColor
title: qsTr("SmartDraw")
flags: Qt.FramelessWindowHint | Qt.Window
header: Rectangle {
id: windowHeader
height: 38
width: parent.width
color: "#0e6afa"
MouseArea {
id: windowResizeUp
height: 2
anchors.bottom: windowDragArea.top
anchors.left: parent.left
anchors.right: minimize.left
cursorShape: Qt.SizeVerCursor
property real lastMousePosY: 0
onPressed: {
lastMousePosY = mouse.y
}
onMouseYChanged:
{
var dy = (mouseY - lastMousePosY)
mainWindow.y += dy
mainWindow.height -= dy
}
}
MouseArea {
id: windowDragArea
height: parent.height - 2
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: minimize.left
property point lastMousePos: Qt.point(0, 0)
onPressed: { lastMousePos = Qt.point(mouseX, mouseY); }
onMouseXChanged: mainWindow.x += (mouseX - lastMousePos.x)
onMouseYChanged: mainWindow.y += (mouseY - lastMousePos.y)
}
Button {
id: minimize
width: 30
height: parent.height
anchors.right: maximize.left
onClicked: mainWindow.showMinimized()
background: Rectangle {
width: parent.width
height: parent.height
color: windowHeader.color
}
Rectangle {
color: "white"
height: 2
width: Math.round(parent.width*(2.0/3.0))
anchors.centerIn: parent
}
}
Button {
id: maximize
width: 30
height: parent.height
anchors.right: close.left
onClicked: mainWindow.visibility == Window.Maximized ? mainWindow.showNormal() : mainWindow.showMaximized()
background: Rectangle {
width: parent.width
height: parent.height
color: windowHeader.color
}
Rectangle {
color: "white"
width: 15
height: 15
}
}
Button {
id: close
width: 30
anchors.right: parent.right
height: parent.height
onClicked: Qt.quit()
background: Rectangle {
width: parent.width
height: parent.height
color: windowHeader.color
}
Text {
color: "white"
text: "X"
}
}
}
footer: Rectangle {
id: windowFooter
color: "#0e6afa"
height: 23
MouseArea {
id: windowResizeBottomLeft
width: 4
height: 4
anchors.left: parent.left
anchors.bottom: parent.bottom
cursorShape: Qt.SizeBDiagCursor
property point lastMousePos: Qt.point(0,0)
onPressed: {
lastMousePos = Qt.point(mouse.x,mouse.y)
}
onMouseYChanged:
{
var dx = (mouseX - lastMousePos.x)
var dy = (mouseY - lastMousePos.y)
mainWindow.x += dx
mainWindow.width -= dx
mainWindow.height += dy
}
}
MouseArea {
id: windowResizeDown
x: 4
height: 2
anchors.bottom: parent.bottom
anchors.left: windowResizeBottomLeft.right
anchors.right: parent.right
cursorShape: Qt.SizeVerCursor
property real lastMousePosY: 0
onPressed: {
lastMousePosY = mouse.y
}
onMouseYChanged:
{
var dy = (mouseY - lastMousePosY)
mainWindow.height += dy
}
}
}
}
主题.qml
pragma Singleton
import QtQuick 2.8
QtObject {
//Text Properties
readonly property fontSize:
readonly property color primaryTextColor: "#D0D0D0"
readonly property color disabledTextColor: "#909090"
//F
readonly property color focusedIconColor: "#D0D0D0"
readonly property color diabledIconColor:
readonly property color primaryBackgroundColor: "#2A2A2A"
readonly property color secondaryBackgroundColor: "#363636"
//All Button Properties
readonly property color disabledButtonColor: "#777777"
//Primary Button Properties
readonly property real primaryButtonBorderWidth: 2
readonly property real primaryButtonBorderRadius: 5
readonly property color primaryButtonBorderColor: "#D0D0D0"
readonly property color primaryButtonColor: "#007acc"
readonly property color primaryButtonHoverColor: "#018deb"
readonly property color primaryButtonPressedColor: "#0165a8"
//Toolbar Button Properties
}
加载 QML 文件
#Setup the application window & configure for high Dpi
os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1"
app = QGuiApplication(sys.argv)
app.setAttribute(Qt.AA_EnableHighDpiScaling)
#Initialize the QML rendering engine
engine = QQmlApplicationEngine()
#Load the main window element
ctx = engine.rootContext()
qml_file = os.path.join(dirname,'qml','main.qml')
engine.load(QUrl.fromLocalFile(os.path.abspath(qml_file)))
#Show the Application Window
win = engine.rootObjects()[0]
win.show()
#Execute and cleanup
app.exec_()
解决方案
一个简单的选择是使用 qresource,但在此之前,您的文件夹 Themes 需要创建一个 qmldir:
qmldir
singleton Theme 1.0 Theme.qml
因此,最终您的项目将具有以下结构:
|-- main.py
`-- qml
|-- Themes
| |-- Theme.qml
| `-- qmldir
`-- main.qml
现在创建一个包含 .qml 的 .qrc 并将其放在 .py 的一侧:
qml.qrc
<RCC>
<qresource prefix="/">
<file>qml/main.qml</file>
<file>qml/Themes/Theme.qml</file>
<file>qml/Themes/qmldir</file>
</qresource>
</RCC>
现在您必须使用 pyrcc5 将 .qrc 转换为 .py:
pyrcc5 qml.qrc -o qml_rc.py
获得以下结构:
|-- main.py
|-- qml
| |-- Themes
| | |-- Theme.qml
| | `-- qmldir
| `-- main.qml
|-- qml.qrc
`-- qml_rc.py
然后你必须导入qml_rc.py
并main.py
修改QUrl
:
import os
import sys
from PyQt5 import QtCore, QtGui, QtQml
import qml_rc
if __name__ == '__main__':
os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1"
app = QtGui.QGuiApplication(sys.argv)
app.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
#Initialize the QML rendering engine
engine = QtQml.QQmlApplicationEngine()
#Load the main window element
ctx = engine.rootContext()
engine.load(QtCore.QUrl("qrc:/qml/main.qml"))
#Show the Application Window
if not engine.rootObjects():
sys.exit(-1)
#Execute and cleanup
sys.exit(app.exec_())
你可以在这里找到完整的项目
更新:
您也可以忽略 .qrc:
|-- main.py
`-- qml
|-- Themes
| |-- Theme.qml
| `-- qmldir
`-- main.qml
使用以下 main.py:
import os
import sys
from PyQt5 import QtCore, QtGui, QtQml
if __name__ == '__main__':
os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1"
app = QtGui.QGuiApplication(sys.argv)
app.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
#Initialize the QML rendering engine
engine = QtQml.QQmlApplicationEngine()
#Load the main window element
ctx = engine.rootContext()
dirname = os.path.dirname(os.path.abspath(__file__))
qml_file = os.path.join(dirname, 'qml','main.qml')
engine.load(QtCore.QUrl.fromLocalFile(qml_file))
#Show the Application Window
if not engine.rootObjects():
sys.exit(-1)
#Execute and cleanup
sys.exit(app.exec_())
你可以在这里找到完整的项目
推荐阅读
- html - 似乎无法在图像上找到文本的问题,尝试在父元素上使用真实和绝对定位,但没有任何效果
- c++ - 如何将 $ 符号添加到 Code::Blocks 中的默认代码?
- java - Android Studio 运行时错误 - 致命异常:主要“无法启动活动”
- gitlab - 我们如何以编程方式批准 GitLab 中的合并请求?
- c# - 在编辑器中出现 4 个异常/错误,但不知道它们是什么?以及如何修复它们?
- winapi - CreateThread() 是“同步点”吗?
- cordova - 为什么会出现错误:82:变量名无效。必须以字母开头,但是是:'proguard
- json - 有没有办法从 gradle 依赖项中提取项目 URL 和最新可用版本?
- python - 异步和线程
- sql - OracleOperator 中的 CREATE 和 DROP 命令失败