Unsolved after creation dynamic component they don't see
-
I have creare a function in javascript (see down) for create dynamic component ( start from here : http://doc.qt.io/qt-5/qtqml-javascript-dynamicobjectcreation.html )
The qml is a sample rectangle :import QtQuick 2.0 Rectangle { width: 80; height: 50; color: "red" }
Why I don' see the object rectangle ???
The function
var componentQmlFile; var objComponentCreate; function createComponentObjects(typeComponentQmlFile, idAreaPosition, jsonObjectComponent) { componentQmlFile = Qt.createComponent(typeComponentQmlFile); if (componentQmlFile.status == Component.Ready) { finishCreation(idAreaPosition, jsonObjectComponent ); } else { componentQmlFile.statusChanged.connect(finishCreation); } } function finishCreation(idAreaPosition, jsonObjectComponent) { if (componentQmlFile.status == Component.Ready) { objComponentCreate = componentQmlFile.createObject(idAreaPosition, {"x": 20, "y": 20}); if (objComponentCreate == null) { // Error Handling console.log("Error creating object"); } else { var propertyComponent = ""; for (var key in jsonObjectComponent){ var value = jsonObjectComponent[key]; objComponentCreate[key] = value; } console.log("fine applicazione proprieta"); } } else if (componentQmlFile.status == Component.Error) { // Error Handling console.log("Error loading component:", componentQmlFile.errorString()); } }
-
It would be helpful to see a little bit more of your code.
Where is your Window? Where is your call of the function createComponentObjects?
Because probably the mistake is not in the functions as they are from the docs, but instead in your way how to call them ...
-
This post is deleted! -
So, you create a component
componentQmlFile
which in turn you use to create an objectobjComponentCreate
, which apparently is some visual item, since it hasx
andy
properties, and which I assume represent theRectangles
you expect to see.But then you do something like:
objComponentCreate[key] = value;
which essentially redefines
objComponentCreate
as an array. Furthermore, if the (hash)key
is a string, then even this array definition will produce incorrect results, since JavaScript does not support named indices in arrays (although no error/warning will be produced ?)
https://www.w3schools.com/js/js_arrays.asp
In any case, the object
objComponentCreate
you created is replaced by an array with a some values given byvalue
and is no longer a visual Item. -
@Leon_2001 said in after creation dynamic component they don't see:
It would be helpful to see a little bit more of your code.
ok this is complet file QML where i Want insert componentimport QtQuick 2.9 import QtQuick.Window 2.2 import QtQuick.Controls 1.4 import QtQuick.Layouts 1.3 import QtQuick.Dialogs 1.2 import "./js/allproject.js" as GeneralJs import "./js/main.js" as MainJs import "./js/componentCreation.js" as MyComponentCreationJs import "./mycomponent" import FileIO 1.0 //usage: ApplicationWindow { id: window visible: true width: 1024 height: 768 title: qsTr("template base spira") menuBar: MenuBar { Menu { title: "File" MenuItem { text: "Open..." } MenuItem { text: "Close" } } Menu { title: "Edit" MenuItem { text: "Cut" } MenuItem { text: "Copy" } MenuItem { text: "Paste" } MenuSeparator { } MenuItem { text: "Delete" } } } toolBar: ToolBar { RowLayout { ToolButton { iconSource: "images/ic_find_replace_black_24dp.png" } ToolButton { iconSource: "images/ic_print_black_24dp.png" } ToolButton { iconSource: "images/ic_settings_black_24dp.png" } Item { Layout.fillWidth: true } CheckBox { text: "Enabled" checked: true } } } Rectangle { id: idRectTopBottom x: 0 y: 0 width: 1024 height: 80 color: "#ffffff" FileIO { id: myFileLanguageComponent source: ":/json/languageComponent.json" onError: console.log(msg) } Component.onCompleted: { var jsonObject =""; jsonObject = JSON.parse(myFileLanguageComponent.read()); var propertyComponent = ""; for (var key in jsonObject.main.IT.BtnTop01){ var value = jsonObject.main.IT.BtnTop01[key]; if (propertyComponent != "" ){propertyComponent = propertyComponent + ", "}; propertyComponent = propertyComponent + "\"" + key + "\": " + value; } MyComponentCreationJs.createComponentObjects("../mycomponent/ButtonReal.qml", "idRectTopBottom", jsonObject.main.IT.BtnTop01 ); } } Rectangle { id: idRectArea color: "#ffffff" anchors.bottom: parent.bottom anchors.bottomMargin: 60 anchors.right: parent.right anchors.rightMargin: 0 anchors.left: parent.left anchors.leftMargin: 0 anchors.top: idRectTopBottom.bottom anchors.topMargin: 0 SplitView { id: splitView anchors.fill: parent Rectangle { id: idRectAreaSx width: 300 color: "#ffffff" anchors.left: parent.left anchors.leftMargin: 0 anchors.top: parent.top anchors.topMargin: 0 anchors.bottom: parent.bottom anchors.bottomMargin: 0 TreeView { id: treeViewSystem anchors.fill: parent TableViewColumn { title: "Name" role: "fileName" width: 300 } TableViewColumn { title: "Permissions" role: "filePermissions" width: 100 } //model: model } } Rectangle { id: idRecAreaDx color: "#ffffff" anchors.top: parent.top anchors.topMargin: 0 anchors.bottom: parent.bottom anchors.bottomMargin: 0 anchors.left: idRectAreaSx.right anchors.leftMargin: 0 anchors.right: parent.right anchors.rightMargin: 0 } } } Rectangle { id: idRectMessage height: 200 color: "#ffffff" anchors.right: parent.right anchors.rightMargin: 0 anchors.left: parent.left anchors.leftMargin: 0 anchors.top: idRectArea.bottom anchors.topMargin: 0 } statusBar: StatusBar { RowLayout { anchors.fill: parent Label { text: "Read Only" } } } } My scope is populate the rectangle **idRectTopBottom** whith the button component end modify your property (for example text and size) reading from a file json
-
@Diracsbracket
I understand what you say diracsbracket.
When I execute this commandobjComponentCreate[key] = value;
I was trying to dynamically modify the properties of the newly created component by reading the data I set in a json file like this:
{ "main": { "IT": { "BtnTop01": { "width": 100, "height": 28 }, "BtnTop02": { "width": 100, "height": 28 } }, "EN":{ "BtnTop01": { "text": "START" }, "BtnTop02": { "text": "DELETE" } } } }
then, for example
objComponentCreate[key] = value;
in place of
objComponentCreate.width= 100;
Not having reported any kind of error I thought this was possible.
If I have the wrong method how can I dynamically change the properties of an object by reading from a list?
In any case, even without this condition, once the object is created, I do not see it.
Tomorrow I try another very simple project. -
@elicat
Assuming that your JSON parsing works and that you use it to extract properties such asx
,y
,width
,height
,text
for each of yourobjComponentCreate
objects (which are apparently someButton
-derived items), you must do something like:objComponentCreate.x = xValueFromJson objComponentCreate.y = yValueFromJson objComponentCreate.width = widthValueFromJson objComponentCreate.height = heightValueFromJson objComponentCreate.text = textStringFromJson
Since you are looping your JSON key/value pairs, you must therefore do something like:
if (key = "x") objComponentCreate.x = value else if (key = "y") objComponentCreate.y = value ...
or use a
switch/case
statement.Better still is to have temp variables
var xValueFromJson var yValueFromJson var widthValueFromJson var heightValueFromJson var textStringFromJson
and set those to your JSON parsed values as shown above, and then use those variables directly in the object construction
objComponentCreate = componentQmlFile.createObject(idAreaPosition, {"x": xValueFromJson, "y": yValueFromJson, "width": widthValueFromJson, etc...});
Also, make sure those objects have the correct visual item as parent.
-
Good morning Diracsbracket,
I was thinking of creating a more dynamic process. In this way I have to set all the elseif for each property if I do not want to put my hand to the code afterwards. But this is the least evil.I followed your advice and changed the properties setting.
Following the new part of the work (for those who read: when we have solved the post, I publish all the code).function finishCreation(idAreaPosition, jsonObjectComponent) { if (componentQmlFile.status == Component.Ready) { objComponentCreate = componentQmlFile.createObject(idAreaPosition, {"x": 5, "y": 38, color: "green"}); if (objComponentCreate == null) { // Error Handling console.log("Error creating object"); } else { console.log("oggetto creato"); var textPropery = ""; var withPropery = ""; var heightPropery = ""; var propertyComponent = ""; for (var key in jsonObjectComponent){ var value = jsonObjectComponent[key]; if (key == "text") { objComponentCreate.text = value; console.log("assegno a " + idAreaPosition + " la property text: " + " con valore: " + value); } else if (key == "width"){ objComponentCreate.width = value; console.log("assegno a " + idAreaPosition + " la property width: " + " con valore: " + value); } else if (key == "height"){ objComponentCreate.height = value console.log("assegno a " + idAreaPosition + " la property height: " + " con valore: " + value); } /* if (propertyComponent != "" ){propertyComponent = propertyComponent + ", "}; propertyComponent = propertyComponent + "\"" + key + "\": " + value; */ } console.log("fine applicazione proprita"); } } else if (componentQmlFile.status == Component.Error) { // Error Handling console.log("Error loading component:", componentQmlFile.errorString()); } }
But although all the steps are executed without error:
QML debugging is enabled. Only use this in a safe environment. qml: The rectangles completed qml: dentro createComponentObjects qml: dentro status ready qml: oggetto creato qml: assegno a idRectTopBottom la property text: con valore: AVVIA qml: assegno a idRectTopBottom la property width: con valore: 100 qml: assegno a idRectTopBottom la property height: con valore: 28 qml: fine applicazione proprieta
The object is not displayed. What is missing?
below the component file ButtonReal.qml
Button { id: buttonRealBlack width: 120 height: 26 text: qsTr("DEFAULT") antialiasing: false //iconSource: "./images/ic_alarm_on_white_18dp.png" activeFocusOnPress: false tooltip: "digita il comando per confermare" style: ButtonStyle { background: Rectangle { id: rectangleButtonRealBlack anchors.fill: parent color: "#000000" gradient: Gradient { GradientStop { position: 0 ; color: buttonRealBlack.pressed ? "#404040" : "#A0A0A0" } GradientStop { position: 1 ; color: buttonRealBlack.pressed ? "#000000" : "#404040" } } } label: Component { Text { text: buttonRealBlack.text //font: fontSize color: "#FFFFFF" wrapMode: Text.WordWrap verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter anchors.fill: parent } } } }
-
@elicat said in after creation dynamic component they don't see:
idAreaPosition
What is that? It does not seem to be a valid visual Item: it seems to be merely a string, since when you print it:
console.log("assegno a " + idAreaPosition + " la property height: " + " con valore: " + value);
It gives:
qml: assegno a idRectTopBottom la property height: con valore: 28
Whenever you print an object in QML using
console.log
orconsole.debug
, you get an output like this (rect
is aRectangle
in this example):console.debug("This is a " + rect)
This gives:
qml: This is a QQuickRectangle(0x19f7edd77d0)
So you must see the type + the address of the object. That's not what your
idAreaPosition
is. I wager there is a mixup in the way you create yourRectangle
and that you stringified its id. How do you define/createidAreaPosition
? -
@elicat said in after creation dynamic component they don't see:
function finishCreation(idAreaPosition, jsonObjectComponent) {
Hello,
idAreaPosition is a parameter. I pass it when i call
function MyComponentCreationJs.createComponentObjectsRectangle { id: idRectTopBottom x: 0 y: 0 width: 1024 height: 80 color: "#ffffff" FileIO { id: myFileLanguageComponent source: ":/json/languageComponent.json" onError: console.log(msg) } Component.onCompleted: { console.log("The rectangle's completed"); var jsonObject =""; jsonObject = JSON.parse(myFileLanguageComponent.read()); MyComponentCreationJs.createComponentObjects("../mycomponent/ButtonReal.qml", "idRectTopBottom", jsonObject.main.IT.BtnTop01 ); }
This is response with also objet created:
qml: oggetto creato: Button_QMLTYPE_56(0x3d4f8130) qml: assegno a idRectTopBottom la property text: con valore: AVVIA qml: assegno a idRectTopBottom la property width: con valore: 100 qml: assegno a idRectTopBottom la property height: con valore: 28 qml: fine applicazione proprieta
The line assegno etc etc: it are value readed from json for Key main.IT.BtnTop01
{ "main": { "IT": { "BtnTop01": { "text": "AVVIA", "width": 100, "height": 28 }, . . . . }
-
@elicat
You cannot useidAreaPosition
as a parent for the visual objects you create, since you know it is NOT an object, but just "a parameter" as you say.You must use an actual visual object as parent! You cannot not use:
objComponentCreate = componentQmlFile.createObject(idAreaPosition, ...)
Replace
idAreaPosition
in the above line by an actual visual OBJECT in your layout, such as an instance ofRectangle
,Item
,Row
, etc... and NOT byidAreaPosition
which just seems to be a STRING that equalsidRectTopBottom
in your case.Good luck.
-
pity that you can not say bad words in the forum ... I changed and passed as a parameter "this" in place of the id name of the object and everything worked.
MyComponentCreationJs.createComponentObjects("../mycomponent/ButtonReal.qml", this , jsonObject.main.IT.BtnTop01 );
I do not close the post just to take the time to publish in the repository this paret dle design that sees the creation of dynamic objects, taking advantage of property values from a json.
Thanks to everyone and mainly to the patience of Diracsbracket.
Remember that I'm a newbie and I do not even know English very well :-)
-
@elicat said in after creation dynamic component they don't see:
I changed and passed as a parameter "this" in place of the id name of the object and everything worked.
Glad you found it!
Know however that in QML, an object'sid
is equivalent to a pointer/reference to that object, i.e. is equivalent to thethis
pointer.If you have declared the
idRectTopBottom
like this:Rectangle { id: idRectTopBottom }
Then you can use
MyComponentCreationJs.createComponentObjects("../mycomponent/ButtonReal.qml", idRectTopBottom,...)
Your mistake was that you put the id between "" quotes, i.e. making it a string.