Home > Mobile >  Why creating an qml object from c does not show anything on application
Why creating an qml object from c does not show anything on application

Time:10-03

I have a file called "SingleTile.qml" with following content

import QtQuick 2.15

Item {
    width: 100; height: 100

    Rectangle {
        anchors.centerIn: parent
        color: "green"
    }
}

On a button click, i do the following to create an instance of SingleTile.qml

QQmlEngine engine;
QQmlComponent component(&engine,
        QUrl::fromLocalFile("SingleTile.qml"));
QQuickItem *object = qobject_cast<QQuickItem*>(component.create());
object->setProperty("color", "blue");

But this does not show any rectangle on the screen with either green or blue color. Why?

CodePudding user response:

Sorry i don't know what your problem is exactly, because you haven't provided enough information about the issue.

But here are some stuff that maybe causing the issue:

  1. QUrl::fromLocalFile creates an absolute path to the given file at you application's location. In your case i would rather just use the constructor with a "qrc:/SingleTile.qml" this will create a relative path to the Qt resource system.

  2. You should be checking for errors after constructing your QQmlComponent by calling "isError" and "errorString".

  3. You need to specify a visual parent for your created item by setting the "parent" property through "setProperty" or "setParentItem", otherwise there is nowhere that the item can be visualized.

CodePudding user response:

Note there are bugs in your SingleTile component. Firstly the green Rectangle { } actually has zero width and height. To correct that bug, you need to change anchors.centerIn: parent to anchors.fill: parent. The other problem is the color cannot be changed because the parent Item has no color property. To fix that you should bubble up that property from your Rectangle with something like a property alias.

//SingleTile.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
Item {
    width: 100; height: 100
    property alias color: rect.color
    Rectangle {
        id: rect
        anchors.fill: parent
        color: "green"
    }
}

Do you require to dynamically create your components in c ? If the button click is done in QML, you can handle the dynamic creation and deletion of your components completely in QML.

There is a Qt page that documents the approach https://doc.qt.io/qt-6/qtqml-javascript-dynamicobjectcreation.html

However, if you want to avoid such complexity, you can consider reworking the dynamic creation as a matter of ListModel and delegates as follows. As you add to the ListModel the delegate will instantiate new instance of your component automatically. As you delete from the ListModel, instances of your component will be deleted automatically.

I use this QML online service which demonstrates the dynamic creation and deletion of SingleTile. Since I am using this QML online service it requires me to put everything in one file, so, I have implemented SingleTile as an inline component instead of a separate file.

import QtQuick 2.15
import QtQuick.Controls 2.15

Page {
    anchors.fill: parent
    component SingleTile: Item {
        width: 100; height: 100
        property alias color: rect.color
        Rectangle {
            id: rect
            anchors.fill: parent
            color: "green"
        }
    }
    
    Repeater {
        model: listModel
        delegate: SingleTile {
            x: tileX
            y: tileY
            color: tileColor
            Text {
                text: "X"
                anchors.right: parent.right
                color: "white"
                MouseArea {
                    anchors.fill: parent
                    onClicked: listModel.remove(index)
                }
            }
        }
    }
    
    ListModel {
        id: listModel
    }
    
    Button {
        text: qsTr("Create")
        onPressed: {
            let tileX = Math.floor(Math.random() * parent.width);
            let tileY = Math.floor(Math.random() * parent.height);
            let tileColor = ["green", "blue"][Math.floor(Math.random() * 2)];
            listModel.append( { tileX, tileY, tileColor } );
        }
    }
}

You can Try it Online!

  • Related