Solved 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 codevar 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:
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!!!!
-
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! -
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 ?
-
@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:
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.
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!
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 !!!
-
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"