[Solved] Is it possible to "connect" widgets "incrementally created"?

V3DigitimesV3Digitimes Posts: 3,051

I'm making a script which should allow me to change for instance some numeric values on specific nodes properties in a scene via an interface. Since the elements in the scene are never the same, with never the same count, the interface I create first reads the scene nodes and stores in an array the interesting properties of each interesting node (node index, name, label, classname, values of given properties, etc, etc).

Then I display all this using widgets which are parented to a main DzVGroupBox using a DzGridLayout in order to organise the widgets display.

The first step of the creation of the interface works perfectly, it is done by a loop on the first array I initially created when collecting nodes (the one gathering the key properties I want to act on).

The worry I have is when I have to "connect" the signals of the edition of the sliders and color widgets to the functions they are supposed to launch. I cannot have them working at all. Depending on the way I wrote the script, either the functions I connect were applied as soon as the script launches "even when there should be no "EditEnd()" signal emitted" - I guess it is because there was a () at the end of the function I call), or they were totally inefficient.

I tested two ways to create the "incremental" widgets:

- first way using an incremental name for the widgets (wDialName = "wDial"+k where k is the scene index increment, followed by wDialName  = new DzFloatSlider(wMainGroup).

 - and the second way using an Array including the widgets aWidget[k] = new DzFloatSlider(wMainGroup).

In both cases the widget creation, initialisation (to current value for nodes in the scene), and display in the interface works fine, but the connection fails. Yet there is no error or warning in the console. When I debug, I see no particular issue neither.

This is why I come here to ask the question, is it possible, when widgets are created with loops (or in arrays) method to "connect" them afterwards? Is there a special way to do that ? I also had a look at the QtScript documentation, but I did not found any page about this specific case. So either I have not found out yet how to do this, or it is not possible.

 

Post edited by V3Digitimes on

Comments

  • simtenerosimtenero Posts: 383

    I'm making a script which should allow me to change for instance some numeric values on specific nodes properties in a scene via an interface. Since the elements in the scene are never the same, with never the same count, the interface I create first reads the scene nodes and stores in an array the interesting properties of each interesting node (node index, name, label, classname, values of given properties, etc, etc).

    Then I display all this using widgets which are parented to a main DzVGroupBox using a DzGridLayout in order to organise the widgets display.

    The first step of the creation of the interface works perfectly, it is done by a loop on the first array I initially created when collecting nodes (the one gathering the key properties I want to act on).

    The worry I have is when I have to "connect" the signals of the edition of the sliders and color widgets to the functions they are supposed to launch. I cannot have them working at all. Depending on the way I wrote the script, either the functions I connect were applied as soon as the script launches "even when there should be no "EditEnd()" signal emitted" - I guess it is because there was a () at the end of the function I call), or they were totally inefficient.

    I tested two ways to create the "incremental" widgets:

    - first way using an incremental name for the widgets (wDialName = "wDial"+k where k is the scene index increment, followed by wDialName  = new DzFloatSlider(wMainGroup).

     - and the second way using an Array including the widgets aWidget[k] = new DzFloatSlider(wMainGroup).

    In both cases the widget creation, initialisation (to current value for nodes in the scene), and display in the interface works fine, but the connection fails. Yet there is no error or warning in the console. When I debug, I see no particular issue neither.

    This is why I come here to ask the question, is it possible, when widgets are created with loops (or in arrays) method to "connect" them afterwards? Is there a special way to do that ? I also had a look at the QtScript documentation, but I did not found any page about this specific case. So either I have not found out yet how to do this, or it is not possible.

     

    It's definitely possible to create connections inside a loop.  I've done it once before, so I'm hunting around for some example code to share.  In the meantime, is there any chance you could post a snippet of the loop code you are using?  You're right, you'll need to drop the "()" from the connect statement.

  • rbtwhizrbtwhiz Posts: 2,181

    If you have a valid object that derives from QObject, and that object has the signals you are attempting to connect to, that object can be connected/disconnected at any point during the lifetime of the script. If the signature for the signal isn't correct in the connection statement, the connection will not be established and the function/method you attempted to connect to will not be called when the signal is emitted. If the syntax for the connection to the function/method to be called is incorrect, what you could actually be attempting to connect to is the return value of that function/method rather than the function/method itself.

    Which signal, on which object, are you attempting to connect to which function/method, on which object?

    -Rob

  • V3DigitimesV3Digitimes Posts: 3,051
    edited April 2016

    Thank you for your answers. So it should be possible, I probably simply have a wrong way to set up things.

    Here is the very simplified example of what  I used. Initially I created an Array containing the properties I'm interested in called in my example "aSceneArray". Then I created a basic dialog with a main group and a gridlayout. And here is now time to create the widgets themselves and their connections. Here is what it gives (the "increment name" version, I also have an Array version of it).

    for (k=0; k<aSceneArray.length; k++)	{	wDialName = "wDial"+k; //here I increment the name of the widget with the index	wDialName = new DzFloatSlider(wMainGroup); // I create the widget	wDialName.value = aSceneArray[k][5]; // I initialize the value	connect(wDialName, "editEnd()", ChangeMyValue) // I connect but it does not workfunction ChangeMyValue()	{		ChangeMyValueLoc("X Rotate",aSceneArray[k][0],wDialName.value)	}	}	

    For instance in this one, I would like to have "Xrot" floatsliders for each object

    The function change my values uses as input the property I want to change (X Rotate), aSceneArray[k][0] contains the scene indexes of the objects I'm interested in, and "wDialName.value" is supposed to be the value of the widget wDialName once edited. 

    Re-reading this I tell to myself that I should put the function out of the loop, but in this case, I am not able to link any more to link the index of the widget to one given element in the scene.  Except if I have a way to re-read the widget names... Or if I can increment the name of the functions I use too (is it possible?)

     

    Post edited by V3Digitimes on
  • V3DigitimesV3Digitimes Posts: 3,051
    edited April 2016

    Actually I realise that in the loop as this, the function is always replaced by a new function.

    I have an idea if I cannot sort this out. I can store all the values of the widgets in an array, connect all the widgets "editEnd()" to a single function, and in this function I compare the current values of the widget to the all the stored values. This will allow me to change in the scene only the modified values, on the object I want (and refresh the array of all the values of the widgets). Much more heavy than I expected it to be, but this could be a solution if there is no other.

    edit : HURRAY!!! Just tried this idea and seems to work! I now use one SINGLE function for all. And in this function I compare the values of the widget to the ones my initial array.

    It's "well, solved", but I'm still interested to know, by curiosity, if there is a way to connect the widgets to a function which would use as input variable the index "k" of the widget.

    You helped me a lot because I would not have thought about that otherwise, thanks again. I realised that the issue came from way I connected the function (absolutely wanted to keep the increment thing in the function), I saw the widgets "locally" (limited to their own function), I should have seen the widgets "globally" (a single function for all).

    Post edited by V3Digitimes on
  • rbtwhizrbtwhiz Posts: 2,181

    It would probably be good for you to read the Qt documentation on Using Signals and Slots. The first part is about the C++ side of things, which you can skip. Scroll down and read the "Signal to Function Connections" section, the "Signal to Member Function Connections" section, and the "Signal to Named Member Function Connections" section.

    In the Node Property Sliders sample, the connection statement in the initSlider() function is such that it passes in the slider as the this object for the handleSliderEditEnd() function.

    -Rob

  • V3DigitimesV3Digitimes Posts: 3,051
    edited April 2016
    rbtwhiz said:

    It would probably be good for you to read the Qt documentation on Using Signals and Slots. The first part is about the C++ side of things, which you can skip. Scroll down and read the "Signal to Function Connections" section, the "Signal to Member Function Connections" section, and the "Signal to Named Member Function Connections" section.

    In the Node Property Sliders sample, the connection statement in the initSlider() function is such that it passes in the slider as the this object for the handleSliderEditEnd() function.

    -Rob

    Thank you SO MUCH Rob!!! I went before to this part of Qt Documentation but this was not clear (I mean this is surely clear, but for me, this is so hard to understand).

    The sample script you provide is excellent. It is much more clear, organised, and structured than what I'm doing. 

    I did not know anything about  the "sId = App.createDigest( [ oNode.getLabel(), oProperty.getLabel() ] );" and the "oSliderMap[ sId ] " configuration, so I do all this property by property instead of using the array aPropertyNames, this is why I have presently as many connections and "applyChanges" functions as I have of properties...

    I've already done a lot of things in this project (with my not clear, not organised and not structured way), and I have to decide now wether I restart all from scratch using the principle you used, or if I finsih it the long way. Whatever my choice, I wanted you to know this sample script is "fundamental" for me since before reading and playing a bit with this I was not able to create the "sId" and to update the "oSliderMap" the clean way (with the "property" : oProperty for instance), and now I see the script, I see much better how objects can be used. It's an excellent example in general on how to work with objects, a field I'm too weak on. This is the most clear I example ever seen about "the power of objects" and it will be really useful to me. Thank you :)

     

    Post edited by V3Digitimes on
Sign In or Register to comment.