Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Dynamically adding Text and Image objects
Forum Update on Monday, May 27th 2025

Dynamically adding Text and Image objects

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
3 Posts 2 Posters 1.4k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    tacdin
    wrote on 18 Sept 2021, 13:17 last edited by tacdin
    #1

    Hi, I am trying to code an application demo for my graduation project. As a feature of the demo, the images and textedit part need to be transferred to the user interface. I have a "button" under the section that says "Value" in the first step. When you press this button, buttons that write Text, Image and Export appear in a Popup. Of these buttons, Text and Image are related with function addText and function addImage, which depend on the functions in createobject.js. When you press the button that says Text, the function creates a texteditor in the column whose id is root via ListModel whose id is objectmodel. The TextEditor.qml file it calls provides this. The Image button first opens the folder with the photos on the device via FileDialog. I think the next step should be related to the "onaccepted:" property of FileDialog. I call the addimage function on the onaccepted part, but I have no idea what to write in AddImage.qml for later. How can I relate the source of Image in AddImage.qml with FileDialog? Any ideas and help would be greatly appreciated. thanks.

    Text, Image and Export buttons are in the NavigationBarButton section. The full code is at the bottom. Before, the functions and sections I mentioned are as follows;

    Add Image.png

    • createobject.js is here
    var _component;
    var _callback;
    var _parent;
    var _source;
    
    function create(source, parent, callback)
    {
        _parent = parent;
        _callback = callback;
        _source = source;
    
        _component = Qt.createComponent(source);
        if (_component.status === Component.Ready || _component.status === Component.Error)
            createDone();
        else
            _component.statusChanged.connect(createDone);
    }
    
    function createDone()
    {
        if (_component.status === Component.Ready)
        {
            var obj = _component.createObject(_parent);
            if (obj != null)
                _callback(obj, _source);
            else
                console.log("Error object: " + _source);
    
            _component.destroy();
        }
        else if (_component.status === Component.Error)
            console.log("Error component: " + component.errorString());
    }
    
    

    **

    • function addText() and function addImage are here
        function addText() {
                CreateObject.create("TextEditor.qml", root, itemAdded);
            }
    
            function addImage() {
                CreateObject.create("AddImage.qml", root, itemAdded);
            }
    
            function itemAdded(obj, source) {
                objectsModel.append({"obj": obj, "source": source})
            }
    
    • The itemadded function adds an object to the ListModel dynamically with the append() method.
       function itemAdded(obj, source) {
                objectsModel.append({"obj": obj, "source": source})
            }
    
    • The TextEditor.qml file is implemented from QT's own examples.
    import QtQuick 2.0
    import QtQuick 2.12
    import QtQuick.Controls 2.12
    import QtQuick.Layouts 1.12
    import QtQuick.Window 2.0
    import io.qt.examples.texteditor 1.0
    import QtQuick 2.5
    
    
    
    Rectangle{
    
        visible: true
        width:300
        height:300
        border.color: "black"
        radius: 25
         ToolBar {
            leftPadding: 5
    
            RowLayout {
                anchors.fill: parent
                spacing: 0
    
                ToolButton {
                    id: doneEditingButton
                    font.family: "fontello"
                    text: "\uE80A" // icon-ok
                    opacity: !textArea.readOnly ? 1 : 0
                    onClicked: textArea.readOnly = true
    
                  
                }
            }
        }
    
        DocumentHandler {
            id: document
            document: textArea.textDocument
            cursorPosition: textArea.cursorPosition
            selectionStart: textArea.selectionStart
            selectionEnd: textArea.selectionEnd
            onLoaded: {
                textArea.text = text
            }
            onError: {
                errorDialog.text = message
                errorDialog.visible = true
            }
        }
    
        Flickable {
            id: flickable
            flickableDirection: Flickable.VerticalFlick
            anchors.fill: parent
    
            TextArea.flickable: TextArea {
                id: textArea
                textFormat: Qt.RichText
                wrapMode: TextArea.Wrap
                readOnly: true
                persistentSelection: true
                leftPadding: 6
                rightPadding: 6
                topPadding: 0
                bottomPadding: 0
                background: null
                onLinkActivated: Qt.openUrlExternally(link)
            }
    
            ScrollBar.vertical: ScrollBar {}
        }
    
         ToolBar {
            visible: !textArea.readOnly && textArea.activeFocus
    
       
    
            Flickable {
                anchors.fill: parent
                contentWidth: toolRow.implicitWidth
                flickableDirection: Qt.Horizontal
                boundsBehavior: Flickable.StopAtBounds
    
                Row {
                    id: toolRow
    
                    ToolButton {
                        id: boldButton
                        text: "\uE800" // icon-bold
                        font.family: "fontello"
                        focusPolicy: Qt.NoFocus
                        checkable: true
                        checked: document.bold
                        onClicked: document.bold = !document.bold
                    }
                    ToolButton {
                        id: italicButton
                        text: "\uE801" // icon-italic
                        font.family: "fontello"
                        focusPolicy: Qt.NoFocus
                        checkable: true
                        checked: document.italic
                        onClicked: document.italic = !document.italic
                    }
                    ToolButton {
                        id: underlineButton
                        text: "\uF0CD" // icon-underline
                        font.family: "fontello"
                        focusPolicy: Qt.NoFocus
                        checkable: true
                        checked: document.underline
                        onClicked: document.underline = !document.underline
                    }
    
                    ToolSeparator {}
    
                    ToolButton {
                        id: alignLeftButton
                        text: "\uE803" // icon-align-left
                        font.family: "fontello"
                        focusPolicy: Qt.NoFocus
                        checkable: true
                        checked: document.alignment == Qt.AlignLeft
                        onClicked: document.alignment = Qt.AlignLeft
                    }
                    ToolButton {
                        id: alignCenterButton
                        text: "\uE804" // icon-align-center
                        font.family: "fontello"
                        focusPolicy: Qt.NoFocus
                        checkable: true
                        checked: document.alignment == Qt.AlignHCenter
                        onClicked: document.alignment = Qt.AlignHCenter
                    }
                    ToolButton {
                        id: alignRightButton
                        text: "\uE805" // icon-align-right
                        font.family: "fontello"
                        focusPolicy: Qt.NoFocus
                        checkable: true
                        checked: document.alignment == Qt.AlignRight
                        onClicked: document.alignment = Qt.AlignRight
                    }
                    ToolButton {
                        id: alignJustifyButton
                        text: "\uE806" // icon-align-justify
                        font.family: "fontello"
                        focusPolicy: Qt.NoFocus
                        checkable: true
                        checked: document.alignment == Qt.AlignJustify
                        onClicked: document.alignment = Qt.AlignJustify
                    }
                }
            }
        }
    
        RoundButton {
            id: editButton
            font.family: "fontello"
            text: "\uE809" // icon-pencil
            width: 48
            height: width
            y: parent.height - height - 12
            anchors.right: parent.right
            anchors.margins: 12
            visible: textArea.readOnly
            highlighted: true
    
            onClicked: {
                textArea.readOnly = false
                textArea.forceActiveFocus()
            }
        }
    
    
    
    }
    
    
    • The full code is here;
    import QtQuick 2.6
    import QtQuick.Dialogs 1.2
    import QtQuick.Controls 2.12
    import QtQuick 2.12
    import QtQuick.Layouts 1.12
    import QtGraphicalEffects 1.12
    import "createtextobject.js" as TextCreator
    import "createobject.js" as CreateObject
    ApplicationWindow {
        id:appwindow
        visible: true
        width: 640
        height: 480
        title: qsTr("Demo App")
    
    
        function getControl(){
            return {
    
                data: null,
                getTotalBataryCount:()=>{
                    let battery = 0;
                    for(let i=0;i<this.data.length;i++){
                        battery += ((this.data[i]["battery0.mahConsumed"]!="--.--")?parseFloat(this.data[i]["battery0.mahConsumed"]):0);
                    }
                    return battery;
                },
                getAltitudeCountHigh:()=>{
                    let amslHigh = 0;
                    for(let i=0;i<this.data.length;i++){
                        if((this.data[i]["altitudeAMSL"]>amslHigh)){
                            amslHigh = this.data[i]["altitudeAMSL"];
                        }
                    }
                    return amslHigh;
                },
    
                getTotalFlighttime : ()=> {
                    let flighttime= 0;
                    for(let i=0; i<this.data.length;i++){
                        flighttime += ((this.data[i]["flightTime"]!= "00:00:00")?parseFloat(this.data[i]["flightTime"]):0);
    
                    }
                    return flighttime;
    
    
                },
    
            };
        }
    
        function openFile(fileUrl){
            return new Promise((resolve,reject)=>{
                                   var parser = [];
                                   if (fileUrl.toString())
                                   parser = csvJSON
                                   if (parser) {
                                       var request = new XMLHttpRequest()
                                       request.open('GET', fileUrl)
                                       request.onreadystatechange = function(event) {
                                           if (request.readyState === XMLHttpRequest.DONE) {
                                               let controlObject = getControl();
                                               controlObject.data = parser(request.responseText);
                                               let items= []
                                               items.push(controlObject.getTotalFlighttime().toString(), controlObject.getTotalBataryCount().toString(), controlObject.getAltitudeCountHigh() )
    
    
    
                                               myModel.append({"flightTime": items[0],
                                                                  "battConsump": items[1],
                                                                  "altitude" : items[2]
                                                              })
                                               console.log( "deneme1", controlObject.getTotalFlighttime())
    
                                               console.log("deneme2",controlObject.getTotalBataryCount());
                                               console.log("test",controlObject.getAltitudeCountHigh());
                                               console.log("test2",controlObject.getTotalFlighttime());
                                               resolve(data);
                                           }
    
                                       }
                                       request.send()
    
                                   }
    
                                   reject(false);
                               });
    
        }
    
    
    Image {
    anchors.fill: parent
    source: "qrc:/images/heritage.jpeg"
    id: blurtest
    }
        ListModel {
            id: myModel
            ListElement {
                flightTime:""
                battConsump:""
                altitude:""
    
            }
    
        }
    
        ListView {
            id: viewlist
            width: 350
            height: 200
            //anchors.fill: parent
            model: myModel
            anchors.centerIn: parent
            anchors.left: parent.left
            anchors.leftMargin: 50
            anchors.top: parent.top
            anchors.topMargin: 40
            delegate: GridLayout {
                visible:true
                columns: 3
                columnSpacing: 50
                rowSpacing: 3
    
    
    
                Rectangle{
                    id: flighttimerect
                    width: 75
                    height:75
                    Layout.alignment: Qt.AlignCenter
                    color: "grey"
                    radius: 25
    
                    Label{
                        anchors.centerIn: parent
                        id: flighttimerect1
                        // text: "Total Flight Time:"+ flightTime +"h"
                        color: "grey"
                    }
    
                }
    
                Rectangle {
                    id: batteryconsumptrect
                    width:75
                    height:75
                    Layout.alignment: Qt.AlignHCenter
                    color: "grey"
                    radius: 25
    
                    Label{
                        anchors.centerIn: parent
                        id:batteryconsumptvalue
                        //text: "Battery Consumption:"+ battConsump + "A"
                        color: "black"
                        font.pixelSize: 12
                    }
                }
    
    
                Rectangle {
                    id: altituderect
                    width:75
                    height:75
                    Layout.alignment: Qt.AlignCenter
                    color: "grey"
                    radius: 25
                    Label{
                        anchors.centerIn: parent
                        id:altitudetext
                        //text: "Maximum Altitude:" + altitude+"m"
                        color: "black"
                    }
                }
    
    
                Rectangle{
                    id: valuestest
                    width: 75
                    height:75
                    Layout.alignment: Qt.AlignCenter
                    color: "grey"
                    radius: 25
    
                    Label{
                        anchors.centerIn: parent
                        id: valueslabel1
                        // text: "Total Flight Time:"+ flightTime +"h"
                        color: "grey"
                    }
    
                }
    
    
                Rectangle{
                    id: valuestest2
                    width: 75
                    height:75
                    Layout.alignment: Qt.AlignCenter
                    color: "grey"
                    radius: 25
    
                    Label{
                        anchors.centerIn: parent
                        id: valueslabel2
                        //text: "Total Flight Time:"+ flightTime +"h"
                        color: "grey"
                    }
    
                }
    
    
    
                Rectangle{
                    id: valuestest3
                    width: 75
                    height:75
                    Layout.alignment: Qt.AlignCenter
                    color: "grey"
                    radius: 25
    
                    Label{
                        anchors.centerIn: parent
                        id: valueslabel3
                        // text: "Total Flight Time:"+ flightTime +"h"
                        color: "grey"
                    }
    
                }
    
    
    
                Rectangle{
                    id: valuestest4
                    width: 75
                    height:75
                    Layout.alignment: Qt.AlignCenter
                    color: "grey"
                    radius: 25
    
                    Label{
                        anchors.centerIn: parent
                        id: valueslabel4
                        //  text: "Total Flight Time:"+ flightTime +"h"
                        color: "grey"
                    }
    
                }
    
                Rectangle{
                    id: valuestest5
                    width: 75
                    height:75
                    Layout.alignment: Qt.AlignCenter
                    color: "grey"
                    radius: 25
    
                    Label{
                        anchors.centerIn: parent
                        id: valueslabel5
                        //text: "Total Flight Time:"+ flightTime +"h"
                        color: "grey"
                        font.pixelSize: 12
                    }
    
                }
                Rectangle{
                    id: valuestest6
                    width: 75
                    height:75
                    Layout.alignment: Qt.AlignCenter
                    color: "grey"
                    radius: 25
    
                    Label{
                        anchors.centerIn: parent
                        id: valueslabel6
                        //text: "Total Flight Time:"+ flightTime +"h"
                        color: "grey"
                        font.pixelSize: 12
                    }
    
                }
    
            }
        }
    
    
        function saveFile(fileUrl, text) {
            var request = new XMLHttpRequest();
            request.open("PUT", fileUrl, false);
            request.send(text);
            return request.status;
        }
    
        function csvJSON(csvText) {
            let lines = [];
            const linesArray = csvText.split('\n');
    
            linesArray.forEach((e, any) => {
                                   const row = e.replace(/[\s]+[,]+|[,]+[\s]+/g, ',').trim();
                                   lines.push(row);
                               });
    
            lines.splice(lines.length - 1, 1);
            const result = [];
            const headers = lines[0].split(",");
    
            for (let i = 1; i < lines.length; i++) {
    
                const obj = {};
                const currentline = lines[i].split(",");
    
                for (let j = 0; j < headers.length; j++) {
                    obj[headers[j]] = currentline[j];
                }
                result.push(obj);
    
    
            }
    
    
            return result;
    
        }
    
    
            FileDialog {
            id: filedialog
            nameFilters: ["Image files (*.png *.jpg)"]
             onAccepted: addImage()
            }
    
        RoundButton {
            visible: true
            x:0
            y:0
            contentItem: Image {
                id: roundbuttonimg
                source: "qrc:/images/plus.png"
                visible: true
                fillMode: Image.PreserveAspectFit
                anchors.centerIn: parent
            }
            onClicked: test123.visible= true
    
    
        }
    
        Popup {
            id:test123
            // visible: angleSlider.pressed ? test123.close() : 1
    
            width: parent.width
            height: parent.height
            modal: true
            padding: 0.0
            background: Item {
    
                ShaderEffectSource {
                    id: effectSource
                    sourceItem:  blurtest
                    anchors.fill: parent
                    sourceRect: Qt.rect(test123.x,test123.y,test123.width,test123.height)
                }
                GaussianBlur{
                    id: blur
                    anchors.fill: effectSource
                    source: effectSource
                    radius: 64
                    samples: radius*2+1
                }
    
            }
            contentItem: Item {
                height:tab.height
                width: tab.width
                visible:true
                anchors.centerIn: parent
                anchors.top: parent.top
                anchors.bottom: parent.bottom
                anchors.rightMargin: 40
                anchors.leftMargin: 40
    
                NavigationBar{
                id:tab
                anchors.left: parent.left
                anchors.leftMargin: 100
                anchors.right: parent.right
                anchors.rightMargin: 200
                anchors.bottom: parent.bottom
                anchors.bottomMargin: 200
                anchors.topMargin: 20
                NavigationBarButton {
                    id:textbutton
                    text: "Text"
                    icon.source: "qrc:/images/file.png"
                    onClicked: {
                        addText()//TextCreator.createTextObject();
                        test123.visible=false
                        console.log("success")        }
                    palette {
                        buttonText: "white"
                        highlight: "white"
                        highlightedText: "white"
                    }
                    background: Rectangle {
                          anchors.fill: parent
                           color: "#CF0730"
                           radius: parent.height * 0.6
                      }
    
                    onCheckedChanged: {
                        if (checked) {
                           // rootmainmenu.color = palette.highlight
                        }
                    }
                }
    
                NavigationBarButton {
                    text: "Image"
                    icon.source: "qrc:/images/image.png"
                    onClicked: {filedialog.open()
                                test123.visible= false
                    }
                    palette {
                        buttonText: "white"
                        highlight: "white"
                        highlightedText: "white"
                    }
                    background: Rectangle {
                          anchors.fill: parent
                           color: "#335A9D"
                           radius: parent.height * 0.6
                      }
    
                    onCheckedChanged: {
                        if (checked) {
                           // rootmainmenu.color = palette.highlight
                        }
                    }
                }
    
    
    
                NavigationBarButton {
                    text: "Export"
                    icon.source: "qrc:/images/export.png"
                    onClicked: stackview.push("Log.qml")
                    palette {
                        buttonText: "white"
                        highlight: "white"
                        highlightedText: "white"
                    }
                    background: Rectangle {
                          anchors.fill: parent
                           color: "#00704A"
                           radius: parent.height * 0.6
                      }
    
                    onCheckedChanged: {
                        if (checked) {
                           // rootmainmenu.color = palette.highlight
                        }
                    }
                }
    
                }
    
            }
    
        }
    
    
    
            function addText() {
                CreateObject.create("TextEditor.qml", root, itemAdded);
            }
    
            function addImage() {
                CreateObject.create("AddImage.qml", root, itemAdded);
            }
    
            function itemAdded(obj, source) {
                objectsModel.append({"obj": obj, "source": source})
            }
    
    
    
    
            ListModel {
                    id: objectsModel
                }
    
            Column {
              id: root
            anchors.left: parent.left
            anchors.top: viewlist.bottom
            anchors.topMargin: 10
            anchors.leftMargin: 150
            spacing: 10
            width: 300
    
            }
    
    
    }
    
    
    
    1 Reply Last reply
    0
    • jeremy_kJ Offline
      jeremy_kJ Offline
      jeremy_k
      wrote on 21 Sept 2021, 05:40 last edited by
      #2

      This is a lot of source to understand before beginning to offer an answer. Positioning, formatting, and working features get in the way of understanding the core question. There might be more people willing to tackle it if the scope is limited to a single detail that doesn't work.

      From a glance, it looks like this code is dynamically creating and managing QML objects using imperative javascript. In my experience, this leads to more complex and brittle code. If at all possible, leave that to Loader for single objects, and Repeater or a model + view for a variable number.

      Asking a question about code? http://eel.is/iso-c++/testcase/

      T 1 Reply Last reply 21 Sept 2021, 06:21
      0
      • jeremy_kJ jeremy_k
        21 Sept 2021, 05:40

        This is a lot of source to understand before beginning to offer an answer. Positioning, formatting, and working features get in the way of understanding the core question. There might be more people willing to tackle it if the scope is limited to a single detail that doesn't work.

        From a glance, it looks like this code is dynamically creating and managing QML objects using imperative javascript. In my experience, this leads to more complex and brittle code. If at all possible, leave that to Loader for single objects, and Repeater or a model + view for a variable number.

        T Offline
        T Offline
        tacdin
        wrote on 21 Sept 2021, 06:21 last edited by
        #3

        @jeremy_k Yes you are right about the complexity of the codes, maybe I need to rearrange them before sharing. In case of using Loader and Repeater, will an object be recreated each time? I couldn't understand this part.

        1 Reply Last reply
        0

        1/3

        18 Sept 2021, 13:17

        • Login

        • Login or register to search.
        1 out of 3
        • First post
          1/3
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved