1

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.

1 Answer 1

2

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()
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the solution, it works really well for what I have going. A quick question if you don't mind - I saw that using a Repeater is good for when you need to have duplicate items, which is what I need in this case. But if I ever run into components that don't need a repeater but still need access to the model: manager.model property to be able to customize the value, is that possible?
@SCP3008 Your requirement is unclear, could you give a concrete example
Nevermind, I asked wrong. I've been experimenting with the code some more and I am wondering if it is possible to bring in other widgets like the one above? In the previous example, I just needed a Box that was customizable, and now I am wondering how I can add in a new customizable component with more than 1 customizable field positioned right beneath the current Box component. Should I just ask that in a new post with code example?
@SCP3008 The logic many times is that python provides the data through QObjects or qproperty and makes a binding between those objects. For example let's say that you are going to be a login then create a qproperty that handles the username and another the password then you must make the binding of the text of the items with the qproperties. I recommend you check qmlbook.github.io

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.