使用 Python 初始化和自定义 QML 组件

Initialize and Customize QML Components with Python

有没有办法让我把 QML 组件当作对象,并在 Python 中初始化它们?例如,这是一个盒子的简化 QML: 我希望能够复制构造函数方法在 Java 中的功能。我希望能够通过 Python 脚本自定义每个框上的文本,同时创建多个彼此独立的框实例。

import QtQuick 2.0
import QtQuick.Controls 2.0

Item {
    id: boxItem
    width: 800
    height: 118

    Rectangle {

        id: boxRect
        height: 118
        color: "#55f555"
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.top: parent.top

        Text {
            id: textItem
            width: 463
            height: 43
            color: "#000000"
            text: qsTr("Header Text")
            anchors.left: parent.left
            anchors.top: parent.top
            font.pixelSize: 38
            verticalAlignment: Text.AlignVCenter
            font.family: "Roboto"
            textFormat: Text.AutoText
            anchors.leftMargin: 20
            anchors.topMargin: 20
        }
    }

}

这是我当前的 Python 脚本修改自 Qt 的模板版本:

import os
import sys
from pathlib import Path

import PySide6.QtQml
from PySide6.QtQuick import QQuickView
from PySide6.QtCore import Qt, QUrl
from PySide6.QtGui import QGuiApplication


if __name__ == '__main__':

    #Set up the application window
    app = QGuiApplication(sys.argv)
    view = QQuickView()
    view.setResizeMode(QQuickView.SizeRootObjectToView)

    #Load the QML file
    qml_file = Path(__file__).parent / "Main.qml"
    view.setSource(QUrl.fromLocalFile(os.fspath(qml_file.resolve())))

    #Show the window
    if view.status() == QQuickView.Error:
        sys.exit(-1)
    view.show()

    #execute and cleanup
    app.exec()
    del view

快速说明:我正在使用自定义构建的 QML 组件,而不是尝试编辑 QT 制作的现有组件。

应用另一种技术(编程语言、库、框架)的概念通常不是使用其他技术的好方法。每种技术都有自己的方法和良好实践来实现任何要求。

在 QML 的情况下,其他语言如 C++、python 等通常被认为是实现业务逻辑(类似于后端),QML 负责视图和操作。在这种情况下,建议创建一个 QObject,它提供创建、修改等数据的其他 QObject,这可以反映在视图中。在这种特殊情况下,对于需求,使用模型和自定义 qml Item 就足够了。

Box.qml

import QtQuick 2.0
import QtQuick.Controls 2.0

Item {
    id: boxItem
    width: 800
    height: 118

    property alias text: textItem.text

    Rectangle {

        id: boxRect
        height: 118
        color: "#55f555"
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.top: parent.top

        Text {
            id: textItem
            width: 463
            height: 43
            color: "#000000"
            anchors.left: parent.left
            anchors.top: parent.top
            font.pixelSize: 38
            verticalAlignment: Text.AlignVCenter
            font.family: "Roboto"
            textFormat: Text.AutoText
            anchors.leftMargin: 20
            anchors.topMargin: 20
        }
    }
}

main.qml

import QtQuick 2.0
import QtQuick.Controls 2.0

Item {
    id: root
    ScrollView 
    {
        anchors.fill: parent
        Column{
            Repeater{
                model: manager.model
                Box{
                    text: model.display
                }
            }
        }
    }
}

main.py

import os
import sys
from pathlib import Path


from PySide6.QtCore import Property, QObject, Qt, QUrl
from PySide6.QtGui import QGuiApplication, QStandardItemModel, QStandardItem
from PySide6.QtQuick import QQuickView


class Manager(QObject):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._model = QStandardItemModel()

    @Property(QObject, constant=True)
    def model(self):
        return self._model


if __name__ == "__main__":

    # Set up the application window
    app = QGuiApplication(sys.argv)
    view = QQuickView()
    view.setResizeMode(QQuickView.SizeRootObjectToView)

    manager = Manager()
    view.rootContext().setContextProperty("manager", manager)

    qml_file = Path(__file__).parent / "main.qml"
    view.setSource(QUrl.fromLocalFile(os.fspath(qml_file.resolve())))

    if view.status() == QQuickView.Error:
        sys.exit(-1)
    view.resize(640, 480)
    view.show()

    for i in range(20):
        item = QStandardItem(f"item-{i}")
        manager.model.appendRow(item)

    app.exec()