#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