Инициализация и настройка компонентов QML с помощью Python

#python #qml #pyside6

Вопрос:

Есть ли способ для меня рассматривать компоненты 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.

Ответ №1:

Применение концепций другой технологии (языка программирования, библиотеки, фреймворка) часто является плохим подходом к использованию какой-либо другой технологии. Каждая технология имеет свою собственную методологию и передовой опыт для реализации любых требований.

В случае QML другие языки, такие как C , python и т. Д., Как правило, считаются реализующими бизнес-логику (что-то вроде серверной части), и QML заботится о представлении и операции. В этом случае рекомендуется создать QObject, предоставляющий другие QObject, которые создают, изменяют и т.д. данные и это может быть отражено в представлении. В данном конкретном случае для выполнения требования достаточно использовать модель и пользовательский элемент qml.

Коробка.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()
 

Комментарии:

1. Спасибо за решение, оно действительно хорошо работает для того, что у меня есть. Короткий вопрос, если вы не возражаете — я видел, что использование ретранслятора полезно, когда вам нужны дубликаты предметов, что мне и нужно в данном случае. Но если я когда-нибудь столкнусь с компонентами, которым не нужен повторитель, но все еще нужен доступ к model: manager.model свойству, чтобы иметь возможность настраивать значение, возможно ли это?

2. @SCP3008 Ваше требование неясно, не могли бы вы привести конкретный пример

3. Неважно, я неправильно спросил. Я еще немного поэкспериментировал с кодом, и мне интересно, можно ли использовать другие виджеты, подобные приведенному выше? В предыдущем примере мне просто нужна была настраиваемая коробка, и теперь мне интересно, как я могу добавить новый настраиваемый компонент с более чем 1 настраиваемым полем, расположенным прямо под текущим компонентом коробки. Должен ли я просто спросить об этом в новом посте с примером кода?

4. @SCP3008 Логика часто заключается в том, что python предоставляет данные через QObjects или qproperty и устанавливает привязку между этими объектами. Например, предположим, что вы собираетесь войти в систему, затем создайте свойство qproperty, которое обрабатывает имя пользователя, а другое-пароль, после чего вы должны связать текст элементов с свойствами qproperty. Я рекомендую вам проверить qmlbook.github.io