Creating a Nested Custom QML Component `Component` in a C++ Class












1















The Problem



I am trying to create a QML Component (and by component, I mean a QML component of type Component that gets used by a Loader's sourceComponent property) in a C++ class and pass it down to a QML File. I am using a Loader particularly to dynamically change a single area of the view based on user interaction with the UI elsewhere on that view. Here is how I am approaching the implementation:



DynamicLoader.h



class DynamicLoader: public QQuickItem {
Q_OBJECT
Q_PROPERTY(QObject *mainComp READ getMainComp NOTIFY mainCompChanged)

public:
DynamicLoader(QQuickItem *parent = Q_NULLPTR);

QObject* getMainComp() const;

private:
QObject* m_mainComp;

QObject* createComponent();

signals:
void mainCompChanged();

};


DynamicLoader.cpp



DynamicLoader::DynamicLoader(QQuickItem* parent)
: QQuickItem(parent)
, m_mainComp(new QObject(this)) {
m_mainComp = createCustomComponent();
}

QObject *DynamicLoader::getMainComp() const {
return m_mainComp;
}

QObject* DynamicLoader::createComponent() {
QQmlEngine engine;

QQmlComponent component(&engine,
QUrl::fromLocalFile("://imports/components/CustomComponent.qml"));
QObject* object = component.create();
Q_ASSERT(object);

QQuickItem* childItem = qobject_cast<QQuickItem*>(object);
childItem->setParent(this);
return childItem;
}


CustomComponent.qml



Component {
CustomTextBox {
text: "Custom Text"
}
}


CustomTextBox.qml



import QtQuick 2.0

Item {
property int containerWidth: 580
property alias text: customText.text

anchors.fill: parent

Text {
id: customText
text: "Default Text"
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.weight: Font.Bold
font.pointSize: 100
color: "white"
}
}


This, however, crashes the program with the following error message:



QQmlComponent: Component is not ready, and fails at the Q_ASSERT.



Other Findings



This same error occurs even when CustomComponent.qml is changed to simply Component {}. When I discovered this, I suspected that perhaps QQmlComponent already wraps the QML file with a Component type (please correct me if I am wrong), so I went ahead and converted the file to:



Item {
CustomTextBox {
text: "Custom Text"
}
}


and got the same error.



Only when I change the file to the following does it not error out:



Item {
Item {
}
}


Lastly, the error does not occur when I implement CustomComponent.qml entirely in QML.



Questions




  1. Am I correct in thinking that declaring a QQmlComponent already wraps a QML file with the Component type? If not, how should I be creating a Component QML component in C++?


  2. Why does the program crash when I create a nested custom component? Do I need to create the component through other means?



Any help and corrections to fundamental misconceptions would be greatly appreciated. Thank you.










share|improve this question

























  • Probably you have some error in your costom component and so QML fails to create it.

    – folibis
    Jan 3 at 5:45











  • @folibis that unfortunately is not true. I have confirmed that the nested custom component renders just fine when I implement it entirely through QML.

    – gpsugy
    Jan 3 at 15:47













  • Ok, it would be great if you can provide code of both components so we could test it.

    – folibis
    Jan 3 at 16:32











  • Btw, I've just looked at the question. Do you really wrap one component with another one? How do you thing the inner one should be instantiated?

    – folibis
    Jan 3 at 16:34













  • Thanks for your help. I've updated my entry to include the CustomTextBox.qml file, and modified the CustomComponent.qml accordingly. Can you also elaborate on what you mean by "wrapping one component with another one?" If you meant to ask if I need to, as of now, yet - because I am trying to dynamically set sourceComponent of QML's Loader component. As for your second question, do you mean how each newly generated Component through C++ should be instantiated? In the code I updated the entry with, I imagine a simple setProperty of text with metadata I have retrieved elsewhere.

    – gpsugy
    Jan 3 at 21:15


















1















The Problem



I am trying to create a QML Component (and by component, I mean a QML component of type Component that gets used by a Loader's sourceComponent property) in a C++ class and pass it down to a QML File. I am using a Loader particularly to dynamically change a single area of the view based on user interaction with the UI elsewhere on that view. Here is how I am approaching the implementation:



DynamicLoader.h



class DynamicLoader: public QQuickItem {
Q_OBJECT
Q_PROPERTY(QObject *mainComp READ getMainComp NOTIFY mainCompChanged)

public:
DynamicLoader(QQuickItem *parent = Q_NULLPTR);

QObject* getMainComp() const;

private:
QObject* m_mainComp;

QObject* createComponent();

signals:
void mainCompChanged();

};


DynamicLoader.cpp



DynamicLoader::DynamicLoader(QQuickItem* parent)
: QQuickItem(parent)
, m_mainComp(new QObject(this)) {
m_mainComp = createCustomComponent();
}

QObject *DynamicLoader::getMainComp() const {
return m_mainComp;
}

QObject* DynamicLoader::createComponent() {
QQmlEngine engine;

QQmlComponent component(&engine,
QUrl::fromLocalFile("://imports/components/CustomComponent.qml"));
QObject* object = component.create();
Q_ASSERT(object);

QQuickItem* childItem = qobject_cast<QQuickItem*>(object);
childItem->setParent(this);
return childItem;
}


CustomComponent.qml



Component {
CustomTextBox {
text: "Custom Text"
}
}


CustomTextBox.qml



import QtQuick 2.0

Item {
property int containerWidth: 580
property alias text: customText.text

anchors.fill: parent

Text {
id: customText
text: "Default Text"
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.weight: Font.Bold
font.pointSize: 100
color: "white"
}
}


This, however, crashes the program with the following error message:



QQmlComponent: Component is not ready, and fails at the Q_ASSERT.



Other Findings



This same error occurs even when CustomComponent.qml is changed to simply Component {}. When I discovered this, I suspected that perhaps QQmlComponent already wraps the QML file with a Component type (please correct me if I am wrong), so I went ahead and converted the file to:



Item {
CustomTextBox {
text: "Custom Text"
}
}


and got the same error.



Only when I change the file to the following does it not error out:



Item {
Item {
}
}


Lastly, the error does not occur when I implement CustomComponent.qml entirely in QML.



Questions




  1. Am I correct in thinking that declaring a QQmlComponent already wraps a QML file with the Component type? If not, how should I be creating a Component QML component in C++?


  2. Why does the program crash when I create a nested custom component? Do I need to create the component through other means?



Any help and corrections to fundamental misconceptions would be greatly appreciated. Thank you.










share|improve this question

























  • Probably you have some error in your costom component and so QML fails to create it.

    – folibis
    Jan 3 at 5:45











  • @folibis that unfortunately is not true. I have confirmed that the nested custom component renders just fine when I implement it entirely through QML.

    – gpsugy
    Jan 3 at 15:47













  • Ok, it would be great if you can provide code of both components so we could test it.

    – folibis
    Jan 3 at 16:32











  • Btw, I've just looked at the question. Do you really wrap one component with another one? How do you thing the inner one should be instantiated?

    – folibis
    Jan 3 at 16:34













  • Thanks for your help. I've updated my entry to include the CustomTextBox.qml file, and modified the CustomComponent.qml accordingly. Can you also elaborate on what you mean by "wrapping one component with another one?" If you meant to ask if I need to, as of now, yet - because I am trying to dynamically set sourceComponent of QML's Loader component. As for your second question, do you mean how each newly generated Component through C++ should be instantiated? In the code I updated the entry with, I imagine a simple setProperty of text with metadata I have retrieved elsewhere.

    – gpsugy
    Jan 3 at 21:15
















1












1








1








The Problem



I am trying to create a QML Component (and by component, I mean a QML component of type Component that gets used by a Loader's sourceComponent property) in a C++ class and pass it down to a QML File. I am using a Loader particularly to dynamically change a single area of the view based on user interaction with the UI elsewhere on that view. Here is how I am approaching the implementation:



DynamicLoader.h



class DynamicLoader: public QQuickItem {
Q_OBJECT
Q_PROPERTY(QObject *mainComp READ getMainComp NOTIFY mainCompChanged)

public:
DynamicLoader(QQuickItem *parent = Q_NULLPTR);

QObject* getMainComp() const;

private:
QObject* m_mainComp;

QObject* createComponent();

signals:
void mainCompChanged();

};


DynamicLoader.cpp



DynamicLoader::DynamicLoader(QQuickItem* parent)
: QQuickItem(parent)
, m_mainComp(new QObject(this)) {
m_mainComp = createCustomComponent();
}

QObject *DynamicLoader::getMainComp() const {
return m_mainComp;
}

QObject* DynamicLoader::createComponent() {
QQmlEngine engine;

QQmlComponent component(&engine,
QUrl::fromLocalFile("://imports/components/CustomComponent.qml"));
QObject* object = component.create();
Q_ASSERT(object);

QQuickItem* childItem = qobject_cast<QQuickItem*>(object);
childItem->setParent(this);
return childItem;
}


CustomComponent.qml



Component {
CustomTextBox {
text: "Custom Text"
}
}


CustomTextBox.qml



import QtQuick 2.0

Item {
property int containerWidth: 580
property alias text: customText.text

anchors.fill: parent

Text {
id: customText
text: "Default Text"
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.weight: Font.Bold
font.pointSize: 100
color: "white"
}
}


This, however, crashes the program with the following error message:



QQmlComponent: Component is not ready, and fails at the Q_ASSERT.



Other Findings



This same error occurs even when CustomComponent.qml is changed to simply Component {}. When I discovered this, I suspected that perhaps QQmlComponent already wraps the QML file with a Component type (please correct me if I am wrong), so I went ahead and converted the file to:



Item {
CustomTextBox {
text: "Custom Text"
}
}


and got the same error.



Only when I change the file to the following does it not error out:



Item {
Item {
}
}


Lastly, the error does not occur when I implement CustomComponent.qml entirely in QML.



Questions




  1. Am I correct in thinking that declaring a QQmlComponent already wraps a QML file with the Component type? If not, how should I be creating a Component QML component in C++?


  2. Why does the program crash when I create a nested custom component? Do I need to create the component through other means?



Any help and corrections to fundamental misconceptions would be greatly appreciated. Thank you.










share|improve this question
















The Problem



I am trying to create a QML Component (and by component, I mean a QML component of type Component that gets used by a Loader's sourceComponent property) in a C++ class and pass it down to a QML File. I am using a Loader particularly to dynamically change a single area of the view based on user interaction with the UI elsewhere on that view. Here is how I am approaching the implementation:



DynamicLoader.h



class DynamicLoader: public QQuickItem {
Q_OBJECT
Q_PROPERTY(QObject *mainComp READ getMainComp NOTIFY mainCompChanged)

public:
DynamicLoader(QQuickItem *parent = Q_NULLPTR);

QObject* getMainComp() const;

private:
QObject* m_mainComp;

QObject* createComponent();

signals:
void mainCompChanged();

};


DynamicLoader.cpp



DynamicLoader::DynamicLoader(QQuickItem* parent)
: QQuickItem(parent)
, m_mainComp(new QObject(this)) {
m_mainComp = createCustomComponent();
}

QObject *DynamicLoader::getMainComp() const {
return m_mainComp;
}

QObject* DynamicLoader::createComponent() {
QQmlEngine engine;

QQmlComponent component(&engine,
QUrl::fromLocalFile("://imports/components/CustomComponent.qml"));
QObject* object = component.create();
Q_ASSERT(object);

QQuickItem* childItem = qobject_cast<QQuickItem*>(object);
childItem->setParent(this);
return childItem;
}


CustomComponent.qml



Component {
CustomTextBox {
text: "Custom Text"
}
}


CustomTextBox.qml



import QtQuick 2.0

Item {
property int containerWidth: 580
property alias text: customText.text

anchors.fill: parent

Text {
id: customText
text: "Default Text"
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.weight: Font.Bold
font.pointSize: 100
color: "white"
}
}


This, however, crashes the program with the following error message:



QQmlComponent: Component is not ready, and fails at the Q_ASSERT.



Other Findings



This same error occurs even when CustomComponent.qml is changed to simply Component {}. When I discovered this, I suspected that perhaps QQmlComponent already wraps the QML file with a Component type (please correct me if I am wrong), so I went ahead and converted the file to:



Item {
CustomTextBox {
text: "Custom Text"
}
}


and got the same error.



Only when I change the file to the following does it not error out:



Item {
Item {
}
}


Lastly, the error does not occur when I implement CustomComponent.qml entirely in QML.



Questions




  1. Am I correct in thinking that declaring a QQmlComponent already wraps a QML file with the Component type? If not, how should I be creating a Component QML component in C++?


  2. Why does the program crash when I create a nested custom component? Do I need to create the component through other means?



Any help and corrections to fundamental misconceptions would be greatly appreciated. Thank you.







c++ qt qml






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 3 at 21:13







gpsugy

















asked Jan 2 at 23:03









gpsugygpsugy

309214




309214













  • Probably you have some error in your costom component and so QML fails to create it.

    – folibis
    Jan 3 at 5:45











  • @folibis that unfortunately is not true. I have confirmed that the nested custom component renders just fine when I implement it entirely through QML.

    – gpsugy
    Jan 3 at 15:47













  • Ok, it would be great if you can provide code of both components so we could test it.

    – folibis
    Jan 3 at 16:32











  • Btw, I've just looked at the question. Do you really wrap one component with another one? How do you thing the inner one should be instantiated?

    – folibis
    Jan 3 at 16:34













  • Thanks for your help. I've updated my entry to include the CustomTextBox.qml file, and modified the CustomComponent.qml accordingly. Can you also elaborate on what you mean by "wrapping one component with another one?" If you meant to ask if I need to, as of now, yet - because I am trying to dynamically set sourceComponent of QML's Loader component. As for your second question, do you mean how each newly generated Component through C++ should be instantiated? In the code I updated the entry with, I imagine a simple setProperty of text with metadata I have retrieved elsewhere.

    – gpsugy
    Jan 3 at 21:15





















  • Probably you have some error in your costom component and so QML fails to create it.

    – folibis
    Jan 3 at 5:45











  • @folibis that unfortunately is not true. I have confirmed that the nested custom component renders just fine when I implement it entirely through QML.

    – gpsugy
    Jan 3 at 15:47













  • Ok, it would be great if you can provide code of both components so we could test it.

    – folibis
    Jan 3 at 16:32











  • Btw, I've just looked at the question. Do you really wrap one component with another one? How do you thing the inner one should be instantiated?

    – folibis
    Jan 3 at 16:34













  • Thanks for your help. I've updated my entry to include the CustomTextBox.qml file, and modified the CustomComponent.qml accordingly. Can you also elaborate on what you mean by "wrapping one component with another one?" If you meant to ask if I need to, as of now, yet - because I am trying to dynamically set sourceComponent of QML's Loader component. As for your second question, do you mean how each newly generated Component through C++ should be instantiated? In the code I updated the entry with, I imagine a simple setProperty of text with metadata I have retrieved elsewhere.

    – gpsugy
    Jan 3 at 21:15



















Probably you have some error in your costom component and so QML fails to create it.

– folibis
Jan 3 at 5:45





Probably you have some error in your costom component and so QML fails to create it.

– folibis
Jan 3 at 5:45













@folibis that unfortunately is not true. I have confirmed that the nested custom component renders just fine when I implement it entirely through QML.

– gpsugy
Jan 3 at 15:47







@folibis that unfortunately is not true. I have confirmed that the nested custom component renders just fine when I implement it entirely through QML.

– gpsugy
Jan 3 at 15:47















Ok, it would be great if you can provide code of both components so we could test it.

– folibis
Jan 3 at 16:32





Ok, it would be great if you can provide code of both components so we could test it.

– folibis
Jan 3 at 16:32













Btw, I've just looked at the question. Do you really wrap one component with another one? How do you thing the inner one should be instantiated?

– folibis
Jan 3 at 16:34







Btw, I've just looked at the question. Do you really wrap one component with another one? How do you thing the inner one should be instantiated?

– folibis
Jan 3 at 16:34















Thanks for your help. I've updated my entry to include the CustomTextBox.qml file, and modified the CustomComponent.qml accordingly. Can you also elaborate on what you mean by "wrapping one component with another one?" If you meant to ask if I need to, as of now, yet - because I am trying to dynamically set sourceComponent of QML's Loader component. As for your second question, do you mean how each newly generated Component through C++ should be instantiated? In the code I updated the entry with, I imagine a simple setProperty of text with metadata I have retrieved elsewhere.

– gpsugy
Jan 3 at 21:15







Thanks for your help. I've updated my entry to include the CustomTextBox.qml file, and modified the CustomComponent.qml accordingly. Can you also elaborate on what you mean by "wrapping one component with another one?" If you meant to ask if I need to, as of now, yet - because I am trying to dynamically set sourceComponent of QML's Loader component. As for your second question, do you mean how each newly generated Component through C++ should be instantiated? In the code I updated the entry with, I imagine a simple setProperty of text with metadata I have retrieved elsewhere.

– gpsugy
Jan 3 at 21:15














0






active

oldest

votes












Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54014320%2fcreating-a-nested-custom-qml-component-component-in-a-c-class%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























0






active

oldest

votes








0






active

oldest

votes









active

oldest

votes






active

oldest

votes
















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54014320%2fcreating-a-nested-custom-qml-component-component-in-a-c-class%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

MongoDB - Not Authorized To Execute Command

How to fix TextFormField cause rebuild widget in Flutter

in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith