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

Problem with signal and Dynamic Object created



  • Hello everyone, i'm new in QtQuick and i'm trying to develop an desktop app.
    I've created my custom object, called "TabTPDef". It has a SwipeView with "TapTPMonitor" and "TabTPPrint".
    This object have been dynamically added with the code

     var component;
                           var tab;
                           component = Qt.createComponent("TabTPDef.qml");
        if( component.status != Component.Ready )
        {
            if( component.status == Component.Error )
                console.debug("Error:"+ component.errorString() );
            return;
        }
                           tab= component.createObject(dhsbLink, {objectName:"tp2","buttonId":"i"+2,"monitorId":"m"+2});
    
    

    where "dhsbLink" is the parent, and objectName and buttonId helps me to identify which of these tab is "talking". I have 4 of this TabTPDef dynamically created in dhsbLink.

    I have a slot and a signal to update the monitor. I can update the monitor well, searching the children of dhsbLink and compare the objectName. So if Monitor of TP2 is clicked, the monitor updated is ONLY the TP2. When I dynamically create one "TabTPDef", it fills the monitor well. When i create two of these, the app see two object created and emit the signal twice. If three of TabTPDef are create it emit signal for three times.
    Screen to explain:
    0_1526398974100_easyfull.png
    0_1526398982584_easyfull2.png

    I'm trying to achieve the Qt::DirectConnection, but i don't know if this is the solution.

    Maybe i've explained bad, my English is not so well, so if you don't understand ask me to be more accurate.

    Sorry..

    Thank You!!!!


  • Moderators

    Hi @AboutClod , what is the issue that you have?

    Does this help? See "Connecting Signals to Methods and Signals" at http://doc.qt.io/qt-5/qtqml-syntax-signals.html#connecting-signals-to-methods-and-signals



  • Hi JKSH, i need to be more accurate.

    I've created "TP2" and "TP3" with the statements

    buttTp2.mouseButton.onClicked: {
        var component;
                           var tp2;
                           component = Qt.createComponent("TabTPDef.qml");
        if( component.status != Component.Ready )
        {
            if( component.status == Component.Error )
                console.debug("Error:"+ component.errorString() );
            return;
        }
                           tp2 = component.createObject(dhsbLink{objectName:"tp2","buttonId":"i"+2,"monitorId":"m"+2});
        tp2.anchors.top = dhsbLink.top
        tp2.anchors.topMargin = 100
        tp2.anchors.left = dhsbLink.left
        tp2.anchors.leftMargin = 300
        tp2.anchors.bottom = dhsbLink.bottom
        tp2.frateto.txtButt.text = "TP2";
        tp2.frateto.buttonMain.state = "off"
         tp2.frateto.clicked.connect(buttonClicked);
    }
    
    
    
    
    
    buttTp3.mouseButton.onClicked: {
        var component;
                           var tp3;
                           component = Qt.createComponent("TabTPDef.qml");
                            tp3 = component.createObject(dhsbLink, {objectName:"tp3","buttonId":"i"+3,"monitorId":"m"+3});
    
    
        tp3.anchors.top = dhsbLink.top
        tp3.anchors.topMargin = 100
        tp3.anchors.left = dhsbLink.left
        tp3.anchors.leftMargin = 600
        tp3.anchors.bottom = dhsbLink.bottom
        tp3.frateto.txtButt.text = "TP3";
        tp3.frateto.buttonMain.state = "off"
       tp3.frateto.clicked.connect(buttonClicked);
    
    
    
    }
    

    I connect the clicked signal emitted by TabTPDef here:

    Item {
        id: tabTPDEF
        height: 700
        width: 325
        objectName: "test_rect"
      ...
        SwipeView {
            id: swipe
           currentIndex: 0
           clip: true
            anchors.fill: parent
    
            TabTPMonitor{
            id: frateto
            buttonMain.onClicked: {
                clicked(tabTPDEF.buttonId,tabTPDEF.monitorId)
              }
            }
            TabTP{
             id: viewer
            }
        }
    

    with the function buttonClicked descripted here:

    function buttonClicked(buttonId,monitorId)
       {
    
        for(var i = 0; i <dhsbLink.children.length; i++)
                   {
    
                       if(dhsbLink.children[i].buttonId == buttonId)
                       {
                          if(dhsbLink.children[i].frateto.buttonMain.state=="off"){
                              dhsbLink.children[i].frateto.buttonMain.state="on"
                           easy.open(dhsbLink.children[i].frateto.txtButt.text,i,monitorId)
                          } else {
                             dhsbLink.children[i].frateto.buttonMain.state="off";
                          }
                       }
                       else
                       {
    
                       }
       }
    
    }
    

    where "easy.open(dhsbLink.children[i].frateto.txtButt.text,i,monitorId)" is a c++ method that update the monitor in the screen of the first post, with slot and signal. On Signal Monitor emitted, the text passed by C++ is catch in QML here:

     onSegnaleMonitor: {
     if(dhsbLink.children[children].objectName == trgt ){  
    //trgt is the object name of the "TP" returned by C++
        dhsbLink.children[children].frateto.textArea.text = dhsbLink.children[children].frateto.textArea.text+text+"\n"
                          }      
                }
    }
    

    When I check "onSegnaleMonitor" in the debugger, it made the operation

    dhsbLink.children[children].frateto.textArea.text = dhsbLink.children[children].frateto.textArea.text+text+"\n"
    

    twice if the "TabTPDef" created are two, three times if the "TabTPDef" created are three etc. as seen in the screen of the first post. He recognize who call the "clicked" signal with "dhsbLink.children[children]" and fill the right "TabTPDef", but the signal see two equal object created, and even if the slot is started once, the signal emit twice.

    Thank you!
    and thank you for your patience!


  • Qt Champions 2017

    I read the post and tried to understand what is the issue. It is not very clear to me. Still trying to answer based on what I have understood. If three objects are created, it will make three connects, and it has to emit three signals and hence 3 times slot should be called.

    Your example is big. Can you create simple example and explain the issue ?


  • Moderators

    @dheerendra said in Problem with signal and Dynamic Object created:

    Your example is big. Can you create simple example and explain the issue ?

    I agree with @dheerendra. Please make a smaller example that is easier to understand.



  • Ok guys, i made the example, and found a solution.

    This is my project directory:
    0_1526484752385_1.png

    In main, i define a Item "DhsbLink" as parent and a "Page1a".

    //main.qml
    import QtQuick 2.9
    import QtQuick.Controls 2.2
    
    ApplicationWindow {
        visible: true
        width: 900
        height: 700
        property alias dhsbLink : dhsbLink
        title: qsTr("Tabs")
    
        Item{
            id: dhsbLink
            anchors.fill:parent
    
    
            Page1a {
                id: subtab
            }
    
    
        
    
    
    
        Connections{
            id: link
            target: easyFull
            ignoreUnknownSignals: true
            onSomeSignal: {
    
    
              if(dhsbLink.children[children].monitorId == mId){
                dhsbLink.children[children].txtArea.text =  dhsbLink.children[children].txtArea.text + text + "\n"
                   }
    
                }
            }
        
        
        
        }
    }
    
    

    In "MonitorForm" i create a little monitor, as seen in the original project

    //MonitorForm.ui.qml
    import QtQuick 2.9
    import QtQuick.Controls 2.2
    
    Item {
        id: monitorTab
        width: 400
        height: 400
        property alias monitorTab: monitorTab
        property alias txtArea: txtArea
        property alias starter: starter
        property string monitorId: monitorId
        signal clicked(string mId)
        TextArea {
            id: txtArea
            height: 200
            width: 300
            background: Rectangle {
                anchors.fill: parent
                color: "grey"
            }
    
            Button {
                id: starter
                text: "starter"
                width: 50
                height: 50
            }
        }
    }
    
    

    where I call the signal "clicked" on the button clicked with:

    starter.onClicked: {
    
            clicked(monitorTab.monitorId)
    
    }
    

    Finally In "Page1a" i created a simple button

    ...
            Button {
                id: button
                x: 469
                y: 30
                text: qsTr("Button")
            }
        }
    

    and at onClick and onPressAndHold it creates "Monitor.qml" objects with:

     button.onClicked: {
            var component;
        var sprite;
        component = Qt.createComponent("Monitor.qml");
        sprite = component.createObject(dhsbLink, {objectName:"tp2","monitorId":"m"+1});
    
        sprite.clicked.connect(buttonClicked);
        }
    
        
    
        button.onPressAndHold: {
            var component;
        var sprite;
        component = Qt.createComponent("Monitor.qml");
    
        sprite = component.createObject(dhsbLink, {objectName:"tp3","monitorId":"m"+2, x:400});
            sprite.clicked.connect(buttonClicked);
        }
    

    where i connect the clicked signal with the function buttonClicked descripted in "Page1a"

    function buttonClicked(monitorId) {
            
            for(var i=0;i<dhsbLink.children.length;i++){
            if(dhsbLink.children[i].monitorId == monitorId){
                  easyFull.apreDispositivo(i,monitorId)
            }
        }
    }
    

    The C++ method "apreDispositivo" receives the index of children and the monitorId and call some slots passing the index of the children, some string, and the monitor id

    void easyFull::apreDispositivo(QString children,QString mId)
    {
        int intCont = 1;
        int intResult = 0;
       QString strResult;
         someSlot(children,"LinkConnecting",mId);
       someSlot(children,"LinkConnecting riuscita",mId);
        //txtMonitor.text = "LinkConnecting riuscita";
        intCont = 1;
        someSlot(children,"LinkConnected",mId);
    ...
    

    then the Connection descripted in main.qml :

    Connections{
            id: link
            target: easyFull
            ignoreUnknownSignals: true
            onSomeSignal: {
    
    
              if(dhsbLink.children[children].monitorId == mId){
                dhsbLink.children[children].txtArea.text =  dhsbLink.children[children].txtArea.text + text + "\n"
                   }
    
                }
            }
    

    where "children" is the index of the children passed by C++.

    Result? It works as i want.
    0_1526485687753_2.png
    0_1526485695064_3.png

    So I was searching in my code what could was wrong and I have my Connections {} statement in the "TabTPDef", while in the exampleqt my Connections {} statement was in the main, in the parent where i've created the dynamic object. It was completely wrong. So I moved it in the dhsbLink Tab, and it works as expected!

    0_1526486060672_4.png

    No one string is equal to the previous one, as i want!
    As you can see, the signal for the below text in the pic, is still in the TabTPDef, and it write "1" as many as the created objects.

    The question can be marked as solved.

    I apologize for my previous bad explanation. My english have to be improved. I apologize if I made you waste your time.

    Thank you for your time and your patience, @dheerendra and @JKSH !!!


  • Moderators

    Hi @AboutClod, I'm glad you found a solution.

    Your English is fine and you didn't waste our time. Please don't worry :)

    However, I'd like to suggest some improvements: Your example should be simpler, shorter, and less complex. You code formatting should also be cleaner. If you do this, your examples will be much easier to understand so people can better help you.

    Here is an example of bad formatting:

    button.onClicked: {
           var component;
       var sprite;
       component = Qt.createComponent("Monitor.qml");
       sprite = component.createObject(dhsbLink, {objectName:"tp2","monitorId":"m"+1});
    
       sprite.clicked.connect(buttonClicked);
       }
    

    This is how it should be formatted:

    button.onClicked: {
        var component;
        var sprite;
        component = Qt.createComponent("Monitor.qml");
        sprite = component.createObject(dhsbLink, {objectName:"tp2","monitorId":"m"+1});
    
        sprite.clicked.connect(buttonClicked);
    }
    

    Furthermore, you can shorted your code like this:

    button.onClicked: {
        var component = Qt.createComponent("Monitor.qml");
        var sprite = component.createObject(dhsbLink, {objectName:"tp2","monitorId":"m"+1});
        sprite.clicked.connect(buttonClicked);
    }
    

    @AboutClod said in Problem with signal and Dynamic Object created:

    The question can be marked as solved.

    Please do this: Click "Topic Tools" -> "Mark as Solved"


Log in to reply