Creating a Nested Custom QML Component `Component` in a C++ Class
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
Am I correct in thinking that declaring a QQmlComponent already wraps a QML file with the
Componenttype? If not, how should I be creating aComponentQML component in C++?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
add a comment |
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
Am I correct in thinking that declaring a QQmlComponent already wraps a QML file with the
Componenttype? If not, how should I be creating aComponentQML component in C++?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
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 theCustomTextBox.qmlfile, and modified theCustomComponent.qmlaccordingly. 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 setsourceComponentof QML'sLoadercomponent. 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 simplesetPropertyoftextwith metadata I have retrieved elsewhere.
– gpsugy
Jan 3 at 21:15
add a comment |
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
Am I correct in thinking that declaring a QQmlComponent already wraps a QML file with the
Componenttype? If not, how should I be creating aComponentQML component in C++?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
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
Am I correct in thinking that declaring a QQmlComponent already wraps a QML file with the
Componenttype? If not, how should I be creating aComponentQML component in C++?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
c++ qt qml
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 theCustomTextBox.qmlfile, and modified theCustomComponent.qmlaccordingly. 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 setsourceComponentof QML'sLoadercomponent. 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 simplesetPropertyoftextwith metadata I have retrieved elsewhere.
– gpsugy
Jan 3 at 21:15
add a comment |
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 theCustomTextBox.qmlfile, and modified theCustomComponent.qmlaccordingly. 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 setsourceComponentof QML'sLoadercomponent. 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 simplesetPropertyoftextwith 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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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

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.qmlfile, and modified theCustomComponent.qmlaccordingly. 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 setsourceComponentof QML'sLoadercomponent. 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 simplesetPropertyoftextwith metadata I have retrieved elsewhere.– gpsugy
Jan 3 at 21:15