Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt Creator and other tools
  4. How can I receive signals emitted by setupUI(), to capture the initial state of a widget configured in Qt Designer?

How can I receive signals emitted by setupUI(), to capture the initial state of a widget configured in Qt Designer?

Scheduled Pinned Locked Moved Solved Qt Creator and other tools
11 Posts 4 Posters 3.3k 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.
  • D Offline
    D Offline
    David Williams
    wrote on last edited by
    #1

    I have created a 'SettingsWidget' in which contains some basic controls (checkboxes and spinboxes) and have set the initial values appropriately in Qt Designer. In code I create an instance of SettingsWidget, call setupUI() to create its components, and then hook-up the various xxxChanged() signals to the slots of the object I want to control.

    It works as expected, but unfortunately I do not get a chance to receive the signals when the components are set to their initial state by setupUI(). This is because I setup the connections after setupUI(), and obviously I can't set them up first because the components haven't been created yet.

    That is, setupUI() is an 'atomic' operation which both creates the component widgets and sets their initial state. Ideally this would be split in two so that I could call e.g. 'createUI()', then setup my connections, then call 'setupUI()' and receive the signals as setup occurs. Unfortunately this is not how Qt Designer seems to work.

    Of course, once setupUI() is complete I can write code to read back the state which has been set, but this is extra coupling and feels somewhat hacky. How do people usually handle this setup phase?

    Thanks in advance!

    Note: For completeness, my current solution is to have a 'simulateChanges()' method on my SettingsWidget which I call after I have set the connections up, and which manually emits valueChanged() signals for each component. It feels ugly though and requires me to keep this up-to-date as I add or remove component widgets.

    Note 2: This question was originally posted on StackOverflow

    jsulmJ J.HilkJ 2 Replies Last reply
    0
    • D David Williams

      I have created a 'SettingsWidget' in which contains some basic controls (checkboxes and spinboxes) and have set the initial values appropriately in Qt Designer. In code I create an instance of SettingsWidget, call setupUI() to create its components, and then hook-up the various xxxChanged() signals to the slots of the object I want to control.

      It works as expected, but unfortunately I do not get a chance to receive the signals when the components are set to their initial state by setupUI(). This is because I setup the connections after setupUI(), and obviously I can't set them up first because the components haven't been created yet.

      That is, setupUI() is an 'atomic' operation which both creates the component widgets and sets their initial state. Ideally this would be split in two so that I could call e.g. 'createUI()', then setup my connections, then call 'setupUI()' and receive the signals as setup occurs. Unfortunately this is not how Qt Designer seems to work.

      Of course, once setupUI() is complete I can write code to read back the state which has been set, but this is extra coupling and feels somewhat hacky. How do people usually handle this setup phase?

      Thanks in advance!

      Note: For completeness, my current solution is to have a 'simulateChanges()' method on my SettingsWidget which I call after I have set the connections up, and which manually emits valueChanged() signals for each component. It feels ugly though and requires me to keep this up-to-date as I add or remove component widgets.

      Note 2: This question was originally posted on StackOverflow

      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by
      #2

      @David-Williams You can connect signals to slots in designer, did you try to do so?

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      1
      • D Offline
        D Offline
        David Williams
        wrote on last edited by
        #3

        Thanks for the reply, but in this case the object being controlled by the SettingsWidget is not a GUI component and so does not exist in Designer. It is just an object which does some calculations based on the settings which are provided. Hence it is created in code, and I miss the opportunity to receive the initial signals which are emitted as the SettingsWidget is created by setupUI().

        I feel a nicer solution would be if Designer actually generated three functions. 'createUI()' could create the components and 'initUI()' would initialise them, and setupUI() would then just call these two function. It would be backwards compatible, and in my case I could skip setupUI() and inject my connection code between my own calls to createUI() and initUI().

        But maybe I am still missing a trick somewhere?

        jsulmJ 1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Hi,

          What is usually done is that you create your non-GUI objects, your GUI-objects, connect everything needed and then have a method that loads whatever data is needed and thus will trigger the signals and slots to set everything up. The last part is usually done using a single shot QTimer with a delay of 0 meaning that it will fire the next time the event loop runs.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • D Offline
            D Offline
            David Williams
            wrote on last edited by David Williams
            #5

            Thanks for the reply. After everything is created and connected I could indeed set the controls to the desired initial value through my code, and this will cause the signals to be emitted and the settings to be propagated. However, there are then two places where the initial state is defined - firstly in the Designer property browser and later through my own code (which then overrides whatever was set in Designer). This will be confusing if someone else tries to modify the code base. Furthermore, Designer will validate the initial state at design time (I think...) to ensure that a given component value is between its Designer-specified min and max. This is nicer than the run-time validation which would happen if I set up from code.

            My current approach is in some ways a variation of what you propose - after setup I have code which simply re-emits the signals which were previously emitted (and missed) from setupUI(). But this requires some maintenance each time I add/rename a control, and it would just be nicer to receive the signals the first time.

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              Are you connecting both classes externally ?

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              D 1 Reply Last reply
              0
              • SGaistS SGaist

                Are you connecting both classes externally ?

                D Offline
                D Offline
                David Williams
                wrote on last edited by
                #7

                @SGaist One of the classes (SettingsWidget) is a GUI component but the other class is not, therefore I have no choice but to connect them via my own code outside of Designer. I think this is the crux of the problem - by the time the Designer-generated setupUI() has finished executing the various onChanged() signals from setting the initial values have already been fired and so my connections are set up too late. I can get around it by re-firing the signals manually or setting the values again from code but it just feels a little ugly.

                Perhaps I could alternatively create a proxy widget to expose my non-GUI class to designer, but again it doesn't fee like a very clean solution. If Designer could split 'setupUI()' into 'createUI' and 'initUI()' then I could inject my calls to connect() in between them, but this isn't how it currently works.

                1 Reply Last reply
                0
                • D David Williams

                  Thanks for the reply, but in this case the object being controlled by the SettingsWidget is not a GUI component and so does not exist in Designer. It is just an object which does some calculations based on the settings which are provided. Hence it is created in code, and I miss the opportunity to receive the initial signals which are emitted as the SettingsWidget is created by setupUI().

                  I feel a nicer solution would be if Designer actually generated three functions. 'createUI()' could create the components and 'initUI()' would initialise them, and setupUI() would then just call these two function. It would be backwards compatible, and in my case I could skip setupUI() and inject my connection code between my own calls to createUI() and initUI().

                  But maybe I am still missing a trick somewhere?

                  jsulmJ Offline
                  jsulmJ Offline
                  jsulm
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  @David-Williams You can still connect to slots in your GUI in Designer (not directly to your settings object). And then use your settings object in those slots.

                  https://forum.qt.io/topic/113070/qt-code-of-conduct

                  D 1 Reply Last reply
                  0
                  • jsulmJ jsulm

                    @David-Williams You can still connect to slots in your GUI in Designer (not directly to your settings object). And then use your settings object in those slots.

                    D Offline
                    D Offline
                    David Williams
                    wrote on last edited by
                    #9

                    @jsulm Thanks, I think I might be able to work with this, or at least you have given me some inspiration. I can add some slots to my higher-level GUI (perhaps my MainWindow) and then connect the SettingsWidget's onChanged() signals to those in Designer. The new MainWindow slots could then take care of forwarding the changes to the non-GUI object which should be controlled. At least it seems a bit cleaner than my current solution.

                    I think I'v actually made my life a bit difficult by splitting my application into too many UI files and/or classes. For example, my SettingsWidget (just a collection of spin boxes) is in a seperate UI file from my MainWindow. This makes it quite difficult to connect signals/slots between them as I don't have a 'proper' Designer plugin for the settings widget (just using the 'promote widget' feature to insert one). I think I might revisit some design decisions here.

                    1 Reply Last reply
                    0
                    • D David Williams

                      I have created a 'SettingsWidget' in which contains some basic controls (checkboxes and spinboxes) and have set the initial values appropriately in Qt Designer. In code I create an instance of SettingsWidget, call setupUI() to create its components, and then hook-up the various xxxChanged() signals to the slots of the object I want to control.

                      It works as expected, but unfortunately I do not get a chance to receive the signals when the components are set to their initial state by setupUI(). This is because I setup the connections after setupUI(), and obviously I can't set them up first because the components haven't been created yet.

                      That is, setupUI() is an 'atomic' operation which both creates the component widgets and sets their initial state. Ideally this would be split in two so that I could call e.g. 'createUI()', then setup my connections, then call 'setupUI()' and receive the signals as setup occurs. Unfortunately this is not how Qt Designer seems to work.

                      Of course, once setupUI() is complete I can write code to read back the state which has been set, but this is extra coupling and feels somewhat hacky. How do people usually handle this setup phase?

                      Thanks in advance!

                      Note: For completeness, my current solution is to have a 'simulateChanges()' method on my SettingsWidget which I call after I have set the connections up, and which manually emits valueChanged() signals for each component. It feels ugly though and requires me to keep this up-to-date as I add or remove component widgets.

                      Note 2: This question was originally posted on StackOverflow

                      J.HilkJ Offline
                      J.HilkJ Offline
                      J.Hilk
                      Moderators
                      wrote on last edited by J.Hilk
                      #10

                      @David-Williams
                      to answer to your original post, I usually have have a void setDefaultLayout() function that fills the ui, created by code or by QtDesigner, with values.

                      That way you also have the possibility to reset your ui without restarting.

                      In your special case of a Settings Widget, I usually combine such a widget with QSettings to save values/states. And that basicaly demands a function to fill the ui with the stored values.


                      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                      Q: What's that?
                      A: It's blue light.
                      Q: What does it do?
                      A: It turns blue.

                      1 Reply Last reply
                      0
                      • D Offline
                        D Offline
                        David Williams
                        wrote on last edited by
                        #11

                        Thanks, I think that in summary I will try to restructure my code to capture the initial state through slots in the MainWindow (as described previously), and I will also implement loading of settings via QSettings (at which point the Designer-set values won't mater much anyway).

                        I think I've probably got enough to come up with a solution now, so I'll mark this question as answered. Thanks to all for your input!

                        1 Reply Last reply
                        0

                        • Login

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