Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. what's the best practice to write pure c++ widget without ui form?
Forum Updated to NodeBB v4.3 + New Features

what's the best practice to write pure c++ widget without ui form?

Scheduled Pinned Locked Moved Solved General and Desktop
19 Posts 9 Posters 2.3k Views 5 Watching
  • 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.
  • Axel SpoerlA Offline
    Axel SpoerlA Offline
    Axel Spoerl
    Moderators
    wrote on last edited by
    #4

    https://doc.qt.io/qt-6/qobject.html#setObjectName-1

    Software Engineer
    The Qt Company, Oslo

    1 Reply Last reply
    1
    • Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #5

      Why do you need an object name for every widget at all?

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      A 1 Reply Last reply
      2
      • A aiyolo

        Thanks for you reply!

        Should I put the code in a header like the auto-generated ui header or just write them in my customed widget class(this way might make my widgets containng too much code)?

        And since the Object created manually have no objectname, can I write some function to help us do that? I hope that there a practice that can organize my code and makes my code seems clean.

        C Offline
        C Offline
        ChrisW67
        wrote on last edited by
        #6

        @aiyolo said in what's the best practice to write pure c++ widget without ui form?:

        And since the Object created manually have no objectname, can I write some function to help us do that?

        Take a look at the code that uic generated for any UI file. Everything it does is there, including things like translation support, object names, etc...

        1 Reply Last reply
        1
        • JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by JonB
          #7

          On the subject of creating a GUI application in Creator. I only have Creator 5(?)-ish, whatever came with Qt5 under Ubuntu 22.04, but I would guess it's no different in Creator 13+. I create a large number of tiny, standalone application from scratch (often to answer questions here). For a GUI C++ application the only choice in Creator wizards does allow you to uncheck "create .ui file", which is welcome, but insists on creating a class derived from QWidget or other similar, which in turn is placed into its own .cpp & .h files, in addition to main.cpp. I use this as a quick way of getting the project set up, with .pro file. Then the first thing I have to do (assuming I don't want the extra class files) is remove the #include from main.cpp and delete the class .cpp & .h files. I wish there were a choice for a "skeletal"/"minimal" UI project application, which just gave you the necessary main.cpp and .pro (doubtless equivalent for cmake) file, no extra class, in just the same way as the "empty" C++ Qt console application wizard does.

          1 Reply Last reply
          0
          • Christian EhrlicherC Christian Ehrlicher

            Why do you need an object name for every widget at all?

            A Offline
            A Offline
            aiyolo
            wrote on last edited by
            #8

            @Christian-Ehrlicher I just don't want to write to much boilerplate code

            1 Reply Last reply
            0
            • JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by JonB
              #9

              What "boilerplate code" are you asking @Christian-Ehrlicher about? He is merely saying that although the UI Designer auto-creates a unique object name for each widget, which you would have to do in your own code if you wanted to replicate, there are actually few times when a widget needs an object name so why bother, unless you actively use it which you probably do not?

              1 Reply Last reply
              1
              • A aiyolo

                I have used qt for over 1 year, recently I found that it is quite annoying to change ui, the qt designer is so hard to use, especially when the ui file I want to change contains too many widgets, and sometimes I want to put some contents to another ui file, there is no quick short key to help me do that.
                Now I want to change to use pure c++ to write ui, for me, this way is easier to refactor my code, and friendly to code review.
                Could someone give me any advices on how to do that?

                jeremy_kJ Offline
                jeremy_kJ Offline
                jeremy_k
                wrote on last edited by
                #10

                @aiyolo said in what's the best practice to write pure c++ widget without ui form?:

                I have used qt for over 1 year, recently I found that it is quite annoying to change ui, the qt designer is so hard to use, especially when the ui file I want to change contains too many widgets

                This sounds like a case of decomposing at the wrong level. Create usable components in separate ui files, as you would in C++ classes. Lots of copy any paste usually indicates to me that I need to further decompose.
                I agree that designer/creator is a little clunky to use. Reproducing the boilerplate output of uic usually convinces me that it's worth suffering through the gui, or manually editing the XML.

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

                A 1 Reply Last reply
                1
                • A aiyolo

                  Thanks for you reply!

                  Should I put the code in a header like the auto-generated ui header or just write them in my customed widget class(this way might make my widgets containng too much code)?

                  And since the Object created manually have no objectname, can I write some function to help us do that? I hope that there a practice that can organize my code and makes my code seems clean.

                  Pl45m4P Offline
                  Pl45m4P Offline
                  Pl45m4
                  wrote on last edited by Pl45m4
                  #11

                  @aiyolo said in what's the best practice to write pure c++ widget without ui form?:

                  Should I put the code in a header like the auto-generated ui header or just write them in my customed widget class(this way might make my widgets containng too much code)?

                  It's totally fine to put your UI code for some widget in the widget.cpp and set everything up in widget's c'tor.

                  And since the Object created manually have no objectname, can I write some function to help us do that? I hope that there a practice that can organize my code and makes my code seems clean.

                  I just mentioned the objectname because it's one of the differences people tend to forget about. When you are used to using the UI files, switch to GUI coding and there is that edge case where you need the objectname (nice to have), you will notice that it's empty for manually created QObject types.

                  E.g.:
                  If you want to get that one specfic button from your GUI, you can simply do

                  ui->objectnameOfButton
                  

                  everywhere in your class where your ui-> pointer is available.
                  Without the UI file and if you didn't stored your objects as member of your class, you can "find" them by iterating the object tree / widget's childs, like:

                   // returns first single match
                  QPushButton *myButton = this->findChild<QPushButton *>();
                   // returns a list with all child buttons of "this" widget
                  QList<QPushButton *> allMyButtons = this->findChildren<QPushButton *>();
                  

                  The first line returns the first matched QPushButton "child" of the current class.
                  Can be the button you actually want to address or the button next to it :)
                  When there are multiple, you have to identify them somehow.
                  Easiest way would be by its objectname (that's what this function is also using).
                  So like this:

                  // assuming you've set an objectname before
                  QPushButton *myButton = this->findChild<QPushButton *>("objectnameOfButton");
                  // which is equal to
                  ui->objectnameOfButton
                  

                  You don't need an objectname as being said before, but in some situations it might be helpful to have one, even though there are also workarounds for this.
                  (the need for an objectname can be an indicator of poor or improvable design)


                  If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                  ~E. W. Dijkstra

                  A 1 Reply Last reply
                  1
                  • jeremy_kJ jeremy_k

                    @aiyolo said in what's the best practice to write pure c++ widget without ui form?:

                    I have used qt for over 1 year, recently I found that it is quite annoying to change ui, the qt designer is so hard to use, especially when the ui file I want to change contains too many widgets

                    This sounds like a case of decomposing at the wrong level. Create usable components in separate ui files, as you would in C++ classes. Lots of copy any paste usually indicates to me that I need to further decompose.
                    I agree that designer/creator is a little clunky to use. Reproducing the boilerplate output of uic usually convinces me that it's worth suffering through the gui, or manually editing the XML.

                    A Offline
                    A Offline
                    aiyolo
                    wrote on last edited by
                    #12

                    @jeremy_k So, can I conclude that using gui is more recommended than directly writing the output of uic?

                    jsulmJ 1 Reply Last reply
                    0
                    • Pl45m4P Pl45m4

                      @aiyolo said in what's the best practice to write pure c++ widget without ui form?:

                      Should I put the code in a header like the auto-generated ui header or just write them in my customed widget class(this way might make my widgets containng too much code)?

                      It's totally fine to put your UI code for some widget in the widget.cpp and set everything up in widget's c'tor.

                      And since the Object created manually have no objectname, can I write some function to help us do that? I hope that there a practice that can organize my code and makes my code seems clean.

                      I just mentioned the objectname because it's one of the differences people tend to forget about. When you are used to using the UI files, switch to GUI coding and there is that edge case where you need the objectname (nice to have), you will notice that it's empty for manually created QObject types.

                      E.g.:
                      If you want to get that one specfic button from your GUI, you can simply do

                      ui->objectnameOfButton
                      

                      everywhere in your class where your ui-> pointer is available.
                      Without the UI file and if you didn't stored your objects as member of your class, you can "find" them by iterating the object tree / widget's childs, like:

                       // returns first single match
                      QPushButton *myButton = this->findChild<QPushButton *>();
                       // returns a list with all child buttons of "this" widget
                      QList<QPushButton *> allMyButtons = this->findChildren<QPushButton *>();
                      

                      The first line returns the first matched QPushButton "child" of the current class.
                      Can be the button you actually want to address or the button next to it :)
                      When there are multiple, you have to identify them somehow.
                      Easiest way would be by its objectname (that's what this function is also using).
                      So like this:

                      // assuming you've set an objectname before
                      QPushButton *myButton = this->findChild<QPushButton *>("objectnameOfButton");
                      // which is equal to
                      ui->objectnameOfButton
                      

                      You don't need an objectname as being said before, but in some situations it might be helpful to have one, even though there are also workarounds for this.
                      (the need for an objectname can be an indicator of poor or improvable design)

                      A Offline
                      A Offline
                      aiyolo
                      wrote on last edited by
                      #13

                      @Pl45m4 Thanks for you reply!

                      It's totally fine to put your UI code for some widget in the widget.cpp and set everything up in widget's c'tor.

                      The only concern for me is that not only ui code that I should put in widget's c'tor, but also signal and slot function I need to write for each sub widget, thus my customed widget will contain thounsands of lines of code. For example, in one of my previous project, although I writed the ui of the mainwindow using qt designer, but there are still thousands of lines of code in my mainwindow class, most of codes are about the logic of user interaction.

                      1 Reply Last reply
                      0
                      • A aiyolo

                        @jeremy_k So, can I conclude that using gui is more recommended than directly writing the output of uic?

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

                        @aiyolo said in what's the best practice to write pure c++ widget without ui form?:

                        can I conclude that using gui is more recommended than directly writing the output of uic?

                        There is no recommendation for this. It is your preference.

                        "thus my customed widget will contain thounsands of lines of code" - then split the big class in smaller classes. @jeremy_k already pointed out that you can split your UI stuff in several UI components/widgets and then compose them in your main window.

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

                        1 Reply Last reply
                        2
                        • S Offline
                          S Offline
                          SimonSchroeder
                          wrote on last edited by
                          #15

                          Most of the time I also just put everything into the constructor. If you want to clean it up a little bit, refactor widget creation into a separate function, refactor adding widgets to layouts into a separate function, and refactor connecting slots into a separate function. Sometimes these can even be split up into several functions themselves (or you create several separate classes as suggested). Nothing is preventing you from using more than one .cpp file per class. If you got thousands of lines, split them up into several files, e.g. mywidget_connect.cpp containing the function connecting slots for the class MyWidget.

                          A 1 Reply Last reply
                          0
                          • S SimonSchroeder

                            Most of the time I also just put everything into the constructor. If you want to clean it up a little bit, refactor widget creation into a separate function, refactor adding widgets to layouts into a separate function, and refactor connecting slots into a separate function. Sometimes these can even be split up into several functions themselves (or you create several separate classes as suggested). Nothing is preventing you from using more than one .cpp file per class. If you got thousands of lines, split them up into several files, e.g. mywidget_connect.cpp containing the function connecting slots for the class MyWidget.

                            A Offline
                            A Offline
                            aiyolo
                            wrote on last edited by aiyolo
                            #16

                            @SimonSchroeder said in what's the best practice to write pure c++ widget without ui form?:

                            If you got thousands of lines, split them up into several files, e.g. mywidget_connect.cpp containing the function connecting slots for the class MyWidget.

                            Suppose that A Widget contains B widget, and B widget contains C widget..., then If I want to query the state of each of subwidget of C widget state in class A, I need to write functions for each query.

                            How can I simplify this procedure?

                            // pseudocode
                            struct Params{
                                 QString param1;
                                 QString param2;
                            };
                            
                            class A: public QWidget{
                               Params param;
                            public slots:
                               void on_pushbutton_clicked(){
                                       param.param1 = getLineText();
                                       param.param2 = getButtonText();
                               }
                            public:
                               QString getLineText(){
                                   // here I want to get the text of QLineEdit in Widget c;
                                  // it is quite annoying to write so many functions in A, because we have so many child widget
                               }
                               QString getButtonText(){
                               // here I want to get the text of QPushbutton in Widget c;
                               }
                            };
                            
                            A a = new A;
                            B b = new B;
                            C c = new C;
                            a->addwidget(b)
                            b->addwidget(c)
                            
                            Pl45m4P S 2 Replies Last reply
                            0
                            • A aiyolo

                              @SimonSchroeder said in what's the best practice to write pure c++ widget without ui form?:

                              If you got thousands of lines, split them up into several files, e.g. mywidget_connect.cpp containing the function connecting slots for the class MyWidget.

                              Suppose that A Widget contains B widget, and B widget contains C widget..., then If I want to query the state of each of subwidget of C widget state in class A, I need to write functions for each query.

                              How can I simplify this procedure?

                              // pseudocode
                              struct Params{
                                   QString param1;
                                   QString param2;
                              };
                              
                              class A: public QWidget{
                                 Params param;
                              public slots:
                                 void on_pushbutton_clicked(){
                                         param.param1 = getLineText();
                                         param.param2 = getButtonText();
                                 }
                              public:
                                 QString getLineText(){
                                     // here I want to get the text of QLineEdit in Widget c;
                                    // it is quite annoying to write so many functions in A, because we have so many child widget
                                 }
                                 QString getButtonText(){
                                 // here I want to get the text of QPushbutton in Widget c;
                                 }
                              };
                              
                              A a = new A;
                              B b = new B;
                              C c = new C;
                              a->addwidget(b)
                              b->addwidget(c)
                              
                              Pl45m4P Offline
                              Pl45m4P Offline
                              Pl45m4
                              wrote on last edited by
                              #17

                              @aiyolo said in what's the best practice to write pure c++ widget without ui form?:

                              Suppose that A Widget contains B widget, and B widget contains C widget..., then If I want to query the state of each of subwidget of C widget state in class A, I need to write functions for each query.

                              Send a signal from C to A which notifies and transmits some information


                              If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                              ~E. W. Dijkstra

                              1 Reply Last reply
                              0
                              • A aiyolo

                                @SimonSchroeder said in what's the best practice to write pure c++ widget without ui form?:

                                If you got thousands of lines, split them up into several files, e.g. mywidget_connect.cpp containing the function connecting slots for the class MyWidget.

                                Suppose that A Widget contains B widget, and B widget contains C widget..., then If I want to query the state of each of subwidget of C widget state in class A, I need to write functions for each query.

                                How can I simplify this procedure?

                                // pseudocode
                                struct Params{
                                     QString param1;
                                     QString param2;
                                };
                                
                                class A: public QWidget{
                                   Params param;
                                public slots:
                                   void on_pushbutton_clicked(){
                                           param.param1 = getLineText();
                                           param.param2 = getButtonText();
                                   }
                                public:
                                   QString getLineText(){
                                       // here I want to get the text of QLineEdit in Widget c;
                                      // it is quite annoying to write so many functions in A, because we have so many child widget
                                   }
                                   QString getButtonText(){
                                   // here I want to get the text of QPushbutton in Widget c;
                                   }
                                };
                                
                                A a = new A;
                                B b = new B;
                                C c = new C;
                                a->addwidget(b)
                                b->addwidget(c)
                                
                                S Offline
                                S Offline
                                SimonSchroeder
                                wrote on last edited by
                                #18

                                @aiyolo said in what's the best practice to write pure c++ widget without ui form?:

                                Suppose that A Widget contains B widget, and B widget contains C widget..., then If I want to query the state of each of subwidget of C widget state in class A, I need to write functions for each query.

                                Well, Qt makes it easy to just query the data from the widgets directly. This, however, is not necessarily the intended way. There is a pattern called MVC (model/view/controller). Following that pattern your widgets are just the view and you would have separate variables for your model. In Qt this would mean that for each QLineEdit::textChanged, QPushButton::clicked, etc. signal you would have a signal in your classes B and C that forward each change through a connect. Class A can then have slots for these signals connected which will change the variables of the model. You would then only query the values from the model. However, this is a lot of boilerplate code to write.

                                But why are we writing getters/setters (or signals/slots in this case) in the first place? This is just the cleanest for of object oriented programming. With C++ OOP is not the only tool in your belt. Bjarne Stroustrup (the inventor of C++) advocates to just use public member variables instead of writing getters/setters. The Qt-generated ui-classes (from .ui files) also do this! So, just make your variables public and then you can access e.g. a line edit in class C via a->b->c->lineEdit. If you still want to restrict general acces, use friend classes instead.

                                findChild() has also already be mentioned. If you successively add subwidget to a widget they will get reparented when using layouts. Then, you can use findChild() on the "most parent" widget, e.g. a->findChild<QLineEdit*>("lineEdit") for a line edit located in class C. I don't really like this option as a general solution because the compiler cannot help you to check if the line edit by that name exists.

                                1 Reply Last reply
                                0
                                • A Offline
                                  A Offline
                                  aiyolo
                                  wrote on last edited by
                                  #19

                                  Send a signal from C to A which notifies and transmits some information

                                  This answer is very inspiring to me. Thank you.

                                  1 Reply Last reply
                                  0
                                  • A aiyolo has marked this topic as solved on

                                  • Login

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