Is there a way for me to treat QML components as objects, and initialize them in Python? For instance, here's a simplified QML for a box: I want to be able to replicate what a constructor method can do in Java. I want to be able to customize the text on each box through the Python script and also, at the same time, create multiple box instances that are separate from each other.
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
}
}
}
This is my current Python script modified from Qt's template version:
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
Quick clarification: I am working with custom built QML components, not trying to edit pre-existing ones made by QT.
Applying the concepts of another technology (programming language, library, framework) are often a bad approach to use some other technology. Each technology has its own methodology and good practices to implement any requirement.
In the case of QML the other languages such as C++, python, etc. are generally considered to implement business logic (something like a backend) and QML takes care of the view and the operation. In this case, it is recommended to create a QObject that provides other QObjects that create, modify, etc. the data and this can be reflected in the view. In this particular case, for the requirement, it is enough to use a model and a custom 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()