Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Create QML component from C++. How?



  • Hello all!

    What am I missing? I am trying to create QML dynamically from C++ in following official documentation but got error and QML component do not showing.

    main.qml

    // Application window
    Window {
    
    	property bool isDesktop: GLOBAL.isDesktop();
    	property real scaleRate: width/GLOBAL.uiWidth();
    
    	id: applicationWindow;
    	visible: true;
    	width: isDesktop ? GLOBAL.desktopApplicationWidth() : maximumWidth;
    	height: isDesktop ? GLOBAL.desktopApplicationHeight() : maximumHeight;
    	title: qsTr("QtQuick Hello World");
    
    	Rectangle {
    
    		id: contentWrapper;
    		width: parent.width;
    		height: parent.height;
    		color: COLOR.white();
    
    		Column {
    
    			id: bottomBlock;
    			objectName: "bottomBlock";
    			width: parent.width;
    			anchors.bottom: parent.bottom;
    			spacing: 10;
    
    //			ButtonExit {}
    
    			Item {
    
    				id: paddingButtom;
    				width: parent.width;
    				height: 30;
    			}
    		}
    	}
    }
    
    

    button.qml

    Rectangle {
    
    	id: buttonExit;
    	color: "#000000";
    	width: parent.width * 0.8;
    	height: width * 0.2;
    	anchors.horizontalCenter: parent.horizontalCenter;
    
    	Text {
    
    		id: buttonExitLabel;
    		text: qsTr("Exit");
    		anchors.horizontalCenter: parent.horizontalCenter;
    		anchors.verticalCenter: parent.verticalCenter;
    		color: "#FFFFFF";
    		font.pointSize: 18;
    	}
    
    	MouseArea {
    
    		id: buttonExitArea;
    		anchors.fill: parent;
    		onClicked: {
    			Qt.quit();
    		}
    	}
    }
    

    main.cpp

    int main(int Counter, char *Arguments[]) {
    
    	QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    	QGuiApplication Application(Counter, Arguments);
    
    	QQmlApplicationEngine Engine;
    	Engine.load(QUrl(Main));
    	if (Engine.rootObjects().isEmpty()) {
    		return -1;
    	}
    
    	QObject *oRootObject = dynamic_cast<QObject*>(Engine.rootObjects()[0]);
    	QObject *oBottomBlock = oRootObject->findChild<QObject*>("bottomBlock");
    
    	QQmlComponent oComponent(&Engine,QUrl(QString("qrc:/ButtonExit.qml")),QQmlComponent::PreferSynchronous);
    	QObject *oButtonExit = oComponent.create();
    	oButtonExit->setParent(oBottomBlock);
    
    	return Application.exec();
    }
    

    When I start it got this error's:

    qrc:/ButtonExit.qml:29: TypeError: Cannot read property 'width' of null
    qrc:/ButtonExit.qml:31: TypeError: Cannot read property 'horizontalCenter' of null
    qrc:/ButtonExit.qml:37: TypeError: Cannot read property 'horizontalCenter' of undefined
    qrc:/ButtonExit.qml:38: TypeError: Cannot read property 'verticalCenter' of undefined
    

    It's looks like the Button object do attached to the object but do not see the parent-property in QML. Every property defined through "parent" not working. When I am attaching it directly in QML - everything works fine.



  • When I am dumping children, the button block attached.

    main.cpp

    int main(int Counter, char *Arguments[]) {
    
    	QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    	QGuiApplication Application(Counter, Arguments);
    
    	QQmlApplicationEngine Engine;
    	Engine.load(QUrl(Main));
    	if (Engine.rootObjects().isEmpty()) {
    		return -1;
    	}
    
    	QObject *oRootObject = dynamic_cast<QObject*>(Engine.rootObjects()[0]);
    	QObject *oBottomBlock = oRootObject->findChild<QObject*>("bottomBlock");
    	
    	if (oBottomBlock) {
    		QQmlComponent oComponent(&Engine,QUrl(QString("qrc:/ButtonExit.qml")));
    		QObject *oButtonExit = oComponent.create();
    		oButtonExit->setParent(oBottomBlock);
    		aLOG << oBottomBlock;
    		aLOG << oBottomBlock->children();
    	}
    
    	return Application.exec();
    }
    

    the log from application:

    qrc:/ButtonExit.qml:30: TypeError: Cannot read property 'width' of null
    qrc:/ButtonExit.qml:32: TypeError: Cannot read property 'horizontalCenter' of null
    1567240723538 QQuickColumn(0x7f989ec986e0, name = "bottomBlock")
    1567240723538 (QQuickItem(0x7f989ec989e0, name = "paddingButtom"), QQuickRectangle(0x7f989ecaa530, name = "buttonExit"))
    

    And I've got another question - How to put created object in defined place? For example if I want to place "buttonExit" before "paddingButtom". For now it's after. I understand that children - it's only QObjectList, but how to make specially defined order of this QObjectList. Is there any way to put child in special place?



  • Solution found. There are need to be added not like QObject parent, there need to be done like QQuickItem parent. This solution woks for me now:

    int main(int Counter, char *Arguments[]) {
    
    	QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    	QGuiApplication Application(Counter, Arguments);
    
    	QQmlApplicationEngine Engine;
    	Engine.load(QUrl(Main));
    	if (Engine.rootObjects().isEmpty()) {
    		return -1;
    	}
    
    	QObject *oRootObject = dynamic_cast<QObject*>(Engine.rootObjects()[0]);
    	QObject *oBottomBlock = oRootObject->findChild<QObject*>("bottomBlock");
    
    	if (oBottomBlock) {
    
    		QQmlComponent oComponent(&Engine,QUrl(QString("qrc:/ButtonExit.qml")));
    		QObject *oButtonExit = oComponent.create();
    		QQuickItem *oItemButtonExit = qobject_cast<QQuickItem*>(oButtonExit);
    		oItemButtonExit->setParentItem(qobject_cast<QQuickItem*>(oBottomBlock));
    	}
    
    	return Application.exec();
    }
    

Log in to reply