Python PyQt从不同目录导入QML主题

Python PyQt从不同目录导入QML主题,python,pyqt,qml,pyqt5,Python,Pyqt,Qml,Pyqt5,我在做一个PyQt项目。我想将主题放在不同于主qml的文件夹中,并允许加载不同的主题。我的目录设置如下图所示。如何引用主题中的属性?我计划最终把这变成一个相当大的项目,所以我希望有一个良好的目录结构,使事情井然有序。 目前我没有得到任何例外,但是背景颜色与我的Theme.qml文件中的颜色不匹配 main.qml import QtQuick 2.12 import QtQuick.Layouts 1.12 import QtQuick.Controls 2.12 import QtQuick

我在做一个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
            }
        }
    }
}
Theme.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,但在此之前,您的文件夹主题需要创建qmldir:

qmldir

singleton Theme 1.0 Theme.qml
因此,最终您的项目将具有以下结构:

|-- main.py
`-- qml
    |-- Themes
    |   |-- Theme.qml
    |   `-- qmldir
    `-- main.qml
|-- main.py
|-- qml
|   |-- Themes
|   |   |-- Theme.qml
|   |   `-- qmldir
|   `-- main.qml
|-- qml.qrc
`-- qml_rc.py
现在创建一个包含.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>
获得以下结构:

|-- main.py
`-- qml
    |-- Themes
    |   |-- Theme.qml
    |   `-- qmldir
    `-- main.qml
|-- main.py
|-- qml
|   |-- Themes
|   |   |-- Theme.qml
|   |   `-- qmldir
|   `-- main.qml
|-- qml.qrc
`-- qml_rc.py
然后必须在
main.py
中导入
qml\u rc.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_())

您可以找到完整的项目

K,因此我将其实现为一个构建步骤,以自动构建qrc文件,这非常酷。问题是,我想潜在地重新加载以杀死窗口,然后在运行时用不同的主题重新加载所有内容。在我看来,qrc文件是有限的。有没有可能在没有qrc文件的情况下进行链接?@user2927848您可以在不关闭窗口的情况下加载主题,或者您想将主题添加为插件?如果有其他模式而不使用.qrc,稍后我将添加该方法是的,我希望它们成为插件。基本上,我不希望将一些qml文件烘焙到qml_rc.py中。我的假设是,我必须重新加载qml并关闭窗口,这可能是不正确的。@在我的解决方案中,user2927848只会消除qml_rc的导入,使用您使用的url,我在回答中没有提到的另一件事是,你的Theme.qml是无效的,因为它缺少一些东西:
只读属性fontSize:
什么是fontSize类型和fontSize默认值?,
只读属性颜色diabledIconColor:
diabledIconColor的默认值是什么?是的,我看了你的东西才知道。非常感谢,艾伦斯克!非常有帮助!