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

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!


  • @elicat

    So, you create a component componentQmlFile which in turn you use to create an object objComponentCreate, which apparently is some visual item, since it has x and y properties, and which I assume represent the Rectangles 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 by value 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 component

    import 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 command

    objComponentCreate[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 as x, y, width, height, text for each of your objComponentCreate objects (which are apparently some Button-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?
    0_1532588892118_dynamic_button.png

    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 or console.debug, you get an output like this (rect is a Rectangle 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 your Rectangle and that you stringified its id. How do you define/create idAreaPosition?



  • @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.createComponentObjects

    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: {
                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 use idAreaPosition 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 of Rectangle, Item, Row, etc... and NOT by idAreaPosition which just seems to be a STRING that equals idRectTopBottom 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's id is equivalent to a pointer/reference to that object, i.e. is equivalent to the this 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.


Log in to reply