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. How do I make a custom parent class from a class that inherits from QMainWindow?
QtWS25 Last Chance

How do I make a custom parent class from a class that inherits from QMainWindow?

Scheduled Pinned Locked Moved Unsolved General and Desktop
15 Posts 2 Posters 2.8k 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.
  • G Offline
    G Offline
    graniteDev
    wrote on last edited by graniteDev
    #1

    I have a class that inherits from QMainWindow, I have customized it's layout, provided it with the necessary signals and slots and private functions and variables etc to do what I want, which is act as a template for Qt form classes. This gives me:

    serviceAppLayout.h
    serviceAppLayout.cpp
    serrviceAppLayout.ui

    What I'm trying to do is have Qt form classes inherit this class directly instead of from QMainWindow. That way all the menus and general layout is done. I have different projects that require their own custom service apps. I want the overall layout to be identical, but I don't want to have to recreate the layout for each one. However I've been stumped on how to actually inherit from my serviceAppLayout class in a way that also inherits the ui layout.

    How do I create a Qt Form Class that inherits my class and it's ui layout? I'm rather stumped as to how to proceed. Inheritance is pretty straightforward normally, but throw in the ui file, and the need for connections to add functionality, and I'm not sure how to precede to accomplish this.

    Eventually I just tried

    #include <gmWidgets/serviceAppLayout.h>
    #include <QApplication>
    #include "widgettest1.h"
    #include "widgettest2.h"
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
    
        ServiceAppLayout w;
    
        widgettest1 *widgetTest1_A = new widgettest1(&w);
        widgettest2 *widgetTest2_B = new widgettest2(&w);
    
        w.addCustomWidget(widgetTest1_A, "Test Widget 1");
        w.addCustomWidget(widgetTest2_B, "Test Widget 2");
    
        w.initializeLayout();
        w.show();
    
        return a.exec();
    }
    

    You can see I added some widgets to the layout to test if it was working. I thought I'd achieved my goal, as the widgets loaded and worked, but I then I realized, I can't add any connections or menu items to the class because I can't call "this" from main.cpp.

    It's not what I want, I want a designer form class that inherits my class AND my class's ui layout/connections so that it can then be customized for it's specific roll. How do I do this?

    1 Reply Last reply
    1
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by mrjj
      #2

      Hi
      Can you explain what you need "this" for in main ?
      Except UI struct being private i see nothing to stop you from your goal unless i missed some important goal. I use a BaseDialog for all my Dialogs to include common elements pr default
      which sounds like what you are after-ish.

      G 1 Reply Last reply
      0
      • mrjjM mrjj

        Hi
        Can you explain what you need "this" for in main ?
        Except UI struct being private i see nothing to stop you from your goal unless i missed some important goal. I use a BaseDialog for all my Dialogs to include common elements pr default
        which sounds like what you are after-ish.

        G Offline
        G Offline
        graniteDev
        wrote on last edited by
        #3

        @mrjj
        So when adding menu items, you have to connect the menu item to a slot. In the example code, I'm just creating an instance of ServiceAppLayout, I can't add any menu items because menu items need to be connected to slots, and I can't put the slot in main.cpp and call "this" in the connection to access it.

        If I could inherit from ServiceAppLayout, I could easily create new menu items and connect to them. I tried to figure out if there was a way I could do that programmatically through function calls, but I'm honestly not sure if that's possible. Can you add connections programmatically? wouldn't that necessitate the slot be a lambda - and that the entire lambda be passed into the function as an argument? That doesn't sound like a fun way to do things.

        1 Reply Last reply
        1
        • mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on last edited by mrjj
          #4

          Hi
          You can use lambdas to have "slots" in main
          https://artandlogic.com/2013/09/qt-5-and-c11-lambdas-are-your-friend/
          (in place )

          Or just create a QObject based helper class to hold the slots. So you connect say
          ServiceAppLayout something to helpers object something.

          • Can you add connections programmatically?
            Yes! just use connect statement.
            connect( pointer to instance, signal, pointer to instance, slot )
            Best to use new syntax.
            http://wiki.qt.io/New_Signal_Slot_Syntax

          Im still not 100% i understand you issue. :)
          can you show a line where u need "this" in main to help me understand the actual issue.

          G 1 Reply Last reply
          0
          • mrjjM Offline
            mrjjM Offline
            mrjj
            Lifetime Qt Champion
            wrote on last edited by
            #5

            Oh, wait. You seen a lot of this in connect statements and hence "this" seems important ?
            Normally inside say Mainwindow, often one part of the connect statement is this as slot lives in mainwindow.
            But it dont have to be "this" . its just because, its inside the class in question.

            Its perfectly legal not to have "this"
            connect( ui->someWidget, SIGNAl, ui->OTHER, SLOT( this slot lives in OTHER ))

            G 1 Reply Last reply
            0
            • mrjjM mrjj

              Hi
              You can use lambdas to have "slots" in main
              https://artandlogic.com/2013/09/qt-5-and-c11-lambdas-are-your-friend/
              (in place )

              Or just create a QObject based helper class to hold the slots. So you connect say
              ServiceAppLayout something to helpers object something.

              • Can you add connections programmatically?
                Yes! just use connect statement.
                connect( pointer to instance, signal, pointer to instance, slot )
                Best to use new syntax.
                http://wiki.qt.io/New_Signal_Slot_Syntax

              Im still not 100% i understand you issue. :)
              can you show a line where u need "this" in main to help me understand the actual issue.

              G Offline
              G Offline
              graniteDev
              wrote on last edited by graniteDev
              #6

              @mrjj hmm....maybe it's not as big of an issue, more my trying to do it the hardway ignorantly. I gave thought to a helper class, but only fleetingly thinking that was the incorrect way of doing it in an object oriented paradigm.

              Although I'm still not sure even adding a menu item with a helper class is possible.
              Normally to set up a menu item the code looks like this:

                  utilMenu = menuBar()->addMenu("Utilities");
              
                  // utilites menu list
                  QAction *networkAction = new QAction("Network",this);
              
                  networkAction->setCheckable(false);
              
                  utilMenu->addAction(networkAction);
                  utilMenu->addSeparator();
              
                  connect(networkAction, &QAction::triggered, this, &ServiceAppLayout::onNetworkAction);
              

              and I tried, I can't access utilMenu->addAction from main.cpp even though I made utilMenu
              public.

              w.utilMenu.
              

              Nothing would come up after the "." like normal so I realized something isn't quite right and I can't access those members.

              I take it actually inheriting a class with a custom ui is impossible?

              mrjjM 1 Reply Last reply
              0
              • G graniteDev

                @mrjj hmm....maybe it's not as big of an issue, more my trying to do it the hardway ignorantly. I gave thought to a helper class, but only fleetingly thinking that was the incorrect way of doing it in an object oriented paradigm.

                Although I'm still not sure even adding a menu item with a helper class is possible.
                Normally to set up a menu item the code looks like this:

                    utilMenu = menuBar()->addMenu("Utilities");
                
                    // utilites menu list
                    QAction *networkAction = new QAction("Network",this);
                
                    networkAction->setCheckable(false);
                
                    utilMenu->addAction(networkAction);
                    utilMenu->addSeparator();
                
                    connect(networkAction, &QAction::triggered, this, &ServiceAppLayout::onNetworkAction);
                

                and I tried, I can't access utilMenu->addAction from main.cpp even though I made utilMenu
                public.

                w.utilMenu.
                

                Nothing would come up after the "." like normal so I realized something isn't quite right and I can't access those members.

                I take it actually inheriting a class with a custom ui is impossible?

                mrjjM Offline
                mrjjM Offline
                mrjj
                Lifetime Qt Champion
                wrote on last edited by mrjj
                #7

                @graniteDev
                Well it is inherited already as UI file is just an XML file - Creator uses to create the setupUI() function that contains plain c++ code to create the form layout. 100% like manually code.
                the UI file is not used runtime in anyway.

                I think this is why im not 100% sure what goes wrong or what you try. :)

                1 Reply Last reply
                0
                • mrjjM mrjj

                  Oh, wait. You seen a lot of this in connect statements and hence "this" seems important ?
                  Normally inside say Mainwindow, often one part of the connect statement is this as slot lives in mainwindow.
                  But it dont have to be "this" . its just because, its inside the class in question.

                  Its perfectly legal not to have "this"
                  connect( ui->someWidget, SIGNAl, ui->OTHER, SLOT( this slot lives in OTHER ))

                  G Offline
                  G Offline
                  graniteDev
                  wrote on last edited by
                  #8

                  @mrjj Yes, I understand what "this" is doing. The slot part of the connection just needs to know what object to find the slot in.

                  1 Reply Last reply
                  1
                  • mrjjM Offline
                    mrjjM Offline
                    mrjj
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    Ok, good.
                    Just checking. :)

                    But would utilMenu not live inside the UI ?
                    so its
                    w.UI->utilMenu ?
                    (UI is most likely still private if you didnt move it )

                    G 1 Reply Last reply
                    1
                    • mrjjM mrjj

                      Ok, good.
                      Just checking. :)

                      But would utilMenu not live inside the UI ?
                      so its
                      w.UI->utilMenu ?
                      (UI is most likely still private if you didnt move it )

                      G Offline
                      G Offline
                      graniteDev
                      wrote on last edited by
                      #10

                      @mrjj OH that's a good point - I could have done it that way, but I just made a helper function that allows me to add an action to the menu. I believe now I can connect to it with a helper class....I'll try it and see what happens

                      mrjjM 1 Reply Last reply
                      0
                      • G graniteDev

                        @mrjj OH that's a good point - I could have done it that way, but I just made a helper function that allows me to add an action to the menu. I believe now I can connect to it with a helper class....I'll try it and see what happens

                        mrjjM Offline
                        mrjjM Offline
                        mrjj
                        Lifetime Qt Champion
                        wrote on last edited by mrjj
                        #11

                        @graniteDev
                        Hi
                        Adding a public helper function to allow connects
                        is better design than make UI public.

                        Also as a note.

                        Its also ok to make connect from signal to signal to surface inner widgets signals to the outside.
                        So you declare new public signals and internally hook widget signal to new public signal.

                        Then you can connect from outside to the public signal interface and in that way totally hide
                        what the widgets really are inside. Only signals are visible.
                        If you later change a a widget to other type, you just need to fix the internal mapping.
                        Any external connections still just see the public signal interface and no change is needed.

                        So for example a custom fileDialog have the signal FileSelected that outside can use.
                        What widget internally that actually got the input is not important from outside.
                        They just use FileSelected and knows nothing about its inner design.
                        On larger programs, such details hiding are worth the extra code in gold.

                        G 1 Reply Last reply
                        1
                        • mrjjM mrjj

                          @graniteDev
                          Hi
                          Adding a public helper function to allow connects
                          is better design than make UI public.

                          Also as a note.

                          Its also ok to make connect from signal to signal to surface inner widgets signals to the outside.
                          So you declare new public signals and internally hook widget signal to new public signal.

                          Then you can connect from outside to the public signal interface and in that way totally hide
                          what the widgets really are inside. Only signals are visible.
                          If you later change a a widget to other type, you just need to fix the internal mapping.
                          Any external connections still just see the public signal interface and no change is needed.

                          So for example a custom fileDialog have the signal FileSelected that outside can use.
                          What widget internally that actually got the input is not important from outside.
                          They just use FileSelected and knows nothing about its inner design.
                          On larger programs, such details hiding are worth the extra code in gold.

                          G Offline
                          G Offline
                          graniteDev
                          wrote on last edited by
                          #12

                          @mrjj Ok, thank you for the advice. I have it working.

                          helper.cpp

                          #include "helper.h"
                          #include "exwidget.h"
                          
                          helper::helper(QWidget *parent) : QWidget(parent)
                          {
                          
                          }
                          
                          void helper::callWidget()
                          {
                              ExWidget *exWidget = new ExWidget(this);
                              exWidget->setWindowFlags(Qt::Window);
                              exWidget->setAttribute(Qt::WA_DeleteOnClose);
                              exWidget->setWindowTitle("Vmap Viewer");
                              exWidget->show();
                          }
                          

                          main.cpp

                          #include <serviceAppLayout.h>
                          #include <QApplication>
                          #include <QMenu>
                          #include <QAction>
                          #include "widgettest1.h"
                          #include "widgettest2.h"
                          #include "helper.h"
                          
                          int main(int argc, char *argv[])
                          {
                              QApplication a(argc, argv);
                          
                          
                              ServiceAppLayout w;
                              helper *h = new helper(&w);
                          
                              widgettest1 *widgetTest1_A = new widgettest1(&w);
                              widgettest2 *widgetTest2_B = new widgettest2(&w);
                          
                              w.addCustomWidget(widgetTest1_A, "Test Widget 1");
                              w.addCustomWidget(widgetTest2_B, "Test Widget 2");
                          
                              w.initializeLayout();
                          
                              QAction * testAction = new QAction("Test Menu Item", &w);
                              w.addMenuItem(w.devMenu, testAction);
                              QObject::connect(testAction, &QAction::triggered, h, &helper::callWidget);
                          
                              w.show();
                          
                              return a.exec();
                          }
                          

                          Running it loads the layout, the widgets, and the new menu item, and clicking the menu item launches the widget as desired.

                          Thank you again for your help!

                          1 Reply Last reply
                          0
                          • mrjjM Offline
                            mrjjM Offline
                            mrjj
                            Lifetime Qt Champion
                            wrote on last edited by
                            #13

                            Hi
                            Np :)
                            Super. And you use the new connection syntax :) \o/ +1
                            Just as a note
                            QObject::connect(testAction, &QAction::triggered, h, &helper::callWidget);

                            Could have been made with a lambda to avoid the helper but helper is also fine.

                            G 1 Reply Last reply
                            1
                            • mrjjM mrjj

                              Hi
                              Np :)
                              Super. And you use the new connection syntax :) \o/ +1
                              Just as a note
                              QObject::connect(testAction, &QAction::triggered, h, &helper::callWidget);

                              Could have been made with a lambda to avoid the helper but helper is also fine.

                              G Offline
                              G Offline
                              graniteDev
                              wrote on last edited by
                              #14

                              @mrjj It's true, but I'm trying to avoid piling tons of code into main, and just keep it as much as I can to one line commands. In the actual implementation there will need to be quite a lot more code in the helper file.

                              mrjjM 1 Reply Last reply
                              1
                              • G graniteDev

                                @mrjj It's true, but I'm trying to avoid piling tons of code into main, and just keep it as much as I can to one line commands. In the actual implementation there will need to be quite a lot more code in the helper file.

                                mrjjM Offline
                                mrjjM Offline
                                mrjj
                                Lifetime Qt Champion
                                wrote on last edited by
                                #15

                                @graniteDev
                                That is a good plan.
                                Also a helper class is more OOP than multiple lambdas in main :)

                                1 Reply Last reply
                                1

                                • Login

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