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. Getting QMainWindow to fit its central widget
Forum Updated to NodeBB v4.3 + New Features

Getting QMainWindow to fit its central widget

Scheduled Pinned Locked Moved Solved General and Desktop
14 Posts 3 Posters 10.7k Views 3 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.
  • mrjjM Offline
    mrjjM Offline
    mrjj
    Lifetime Qt Champion
    wrote on last edited by
    #2

    hi
    Im not 100% sure about
    "making the QMainWindow honor the initial size requirement"

    Normally it would be the other way around. Making the
    widget follow size of mainwindow.

    So im not sure why you cannot add a layout to mainwindow
    and add a widget to that. so it follow mainwindow
    then in this widget u can use paintevent for drawing and also
    direct x,y pos since it has no layout inside.

    like this:
    https://www.dropbox.com/s/qsqmcyy977kidwu/harry.zip?dl=0

    the green widget would be your own widget doing drawing.

    H 1 Reply Last reply
    0
    • mrjjM mrjj

      hi
      Im not 100% sure about
      "making the QMainWindow honor the initial size requirement"

      Normally it would be the other way around. Making the
      widget follow size of mainwindow.

      So im not sure why you cannot add a layout to mainwindow
      and add a widget to that. so it follow mainwindow
      then in this widget u can use paintevent for drawing and also
      direct x,y pos since it has no layout inside.

      like this:
      https://www.dropbox.com/s/qsqmcyy977kidwu/harry.zip?dl=0

      the green widget would be your own widget doing drawing.

      H Offline
      H Offline
      Harry123
      wrote on last edited by Harry123
      #3

      @mrjj

      Thanks for answering and for the example.

      I know that QMainWindow has a layout and that is not my problem. The problem is that it resizes the widget. It is the widget that has no layout (or I wouldn't need QMainWindow).

      I would like the widget to start with a size that is determined when creating it - it is not always the same size like in your example, and the painted part is not identical for all invocations. I am forced to embed it in a QMainWindow, because otherwise having a menu is too complicated. But I wish the widget to start initially with a size that is determined at the time of its creation and force the QMainWindow to give the widget that exact size. For future resizes by the user, enlarging or reducing, the QMainWindow may do its stuff in the normal way.

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

        but its still not clear to me why you cannot let the widget follow mainwindow
        and then just set mainwindow to size that allow the size of the widget you want?
        If u set
        ui->IMSELFPAINTED->setMinimumSize(800,600);
        i get green area of that size. and mainwindow somewhat bigger.
        You cannot do like that?

        then later, maybe in showevent, call
        ui->IMSELFPAINTED->setMinimumSize(0,0);
        to allow any resize.

        H 1 Reply Last reply
        1
        • mrjjM mrjj

          but its still not clear to me why you cannot let the widget follow mainwindow
          and then just set mainwindow to size that allow the size of the widget you want?
          If u set
          ui->IMSELFPAINTED->setMinimumSize(800,600);
          i get green area of that size. and mainwindow somewhat bigger.
          You cannot do like that?

          then later, maybe in showevent, call
          ui->IMSELFPAINTED->setMinimumSize(0,0);
          to allow any resize.

          H Offline
          H Offline
          Harry123
          wrote on last edited by Harry123
          #5

          @mrjj

          I currently do use setMinimumSize as a stop-gap measure while developing.

          The setMinimumSize(0,0) solution is certainly much simpler than all my monkeying with size policies.

          Question: Is showEvent for the central widget safe enough, I mean is it done after all size adjustments were already set (at least until some future resize) ?

          mrjjM 1 Reply Last reply
          0
          • H Harry123

            @mrjj

            I currently do use setMinimumSize as a stop-gap measure while developing.

            The setMinimumSize(0,0) solution is certainly much simpler than all my monkeying with size policies.

            Question: Is showEvent for the central widget safe enough, I mean is it done after all size adjustments were already set (at least until some future resize) ?

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

            @Harry123
            well it would be showEvent for mainwindow.
            Normally its safe yes. All sizes set and layouts resolved.

            H 1 Reply Last reply
            1
            • mrjjM mrjj

              @Harry123
              well it would be showEvent for mainwindow.
              Normally its safe yes. All sizes set and layouts resolved.

              H Offline
              H Offline
              Harry123
              wrote on last edited by
              #7

              @mrjj

              Many thanks for the idea - I will be trying that later and will report if problems.

              mrjjM 1 Reply Last reply
              0
              • H Harry123

                @mrjj

                Many thanks for the idea - I will be trying that later and will report if problems.

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

                @Harry123
                Good luck.
                Note.
                I just added layout to mainwindow and then a widget. ( the green one)
                So its not directly on centralwidget.

                H 1 Reply Last reply
                0
                • Chris KawaC Offline
                  Chris KawaC Offline
                  Chris Kawa
                  Lifetime Qt Champion
                  wrote on last edited by Chris Kawa
                  #9

                  You don't need all this toying around. The default size policy is QSizePolicy::Preferred, which means it uses size hint of the widget when it is shown.

                  As for the menu bar - the easiest way is add it to the layout. You don't have to use that layout for any other children. It can be there just for the menu bar and you can place other children manually. Here's a demo:

                  #include <QApplication>
                  #include <QPushButton>
                  #include <QMenuBar>
                  #include <QVBoxLayout>
                  
                  struct Foo : public QWidget {
                      QSize sizeHint() const override { return QSize(400,400); }
                  };
                  
                  int main(int argc, char *argv[]) {
                      QApplication a(argc, argv);
                  
                      Foo foo;
                      foo.setLayout(new QVBoxLayout()); //use a layout for menu bar
                      foo.layout()->setMenuBar(new QMenuBar());
                      foo.layout()->menuBar()->addAction(new QAction("Hi!", &foo));
                  
                      QPushButton* p = new QPushButton(&foo); //don't use layout, place it manually
                      p->move(100,100);
                  
                      foo.show();
                  
                      return a.exec();
                  }
                  

                  If you really don't want the layout for some reason here's the version with main window wrapper, but it's not really necessary:

                  #include <QApplication>
                  #include <QPushButton>
                  #include <QMenuBar>
                  
                  struct Foo : public QWidget {
                      QSize sizeHint() const override { return QSize(400,400); }
                  };
                  
                  int main(int argc, char *argv[])
                  {
                      QApplication a(argc, argv);
                  
                      QMainWindow w;
                      w.setMenuBar(new QMenuBar()); //use the built-in layout for menu bar
                      w.menuBar()->addAction("Hi!");
                      w.setCentralWidget(new Foo); //place the widget in built-in layout
                  
                      QPushButton* p = new QPushButton(w.centralWidget());  //place the child manually
                      p->move(100,100);
                  
                      w.show();
                  
                      return a.exec();
                  }
                  
                  H 1 Reply Last reply
                  1
                  • Chris KawaC Chris Kawa

                    You don't need all this toying around. The default size policy is QSizePolicy::Preferred, which means it uses size hint of the widget when it is shown.

                    As for the menu bar - the easiest way is add it to the layout. You don't have to use that layout for any other children. It can be there just for the menu bar and you can place other children manually. Here's a demo:

                    #include <QApplication>
                    #include <QPushButton>
                    #include <QMenuBar>
                    #include <QVBoxLayout>
                    
                    struct Foo : public QWidget {
                        QSize sizeHint() const override { return QSize(400,400); }
                    };
                    
                    int main(int argc, char *argv[]) {
                        QApplication a(argc, argv);
                    
                        Foo foo;
                        foo.setLayout(new QVBoxLayout()); //use a layout for menu bar
                        foo.layout()->setMenuBar(new QMenuBar());
                        foo.layout()->menuBar()->addAction(new QAction("Hi!", &foo));
                    
                        QPushButton* p = new QPushButton(&foo); //don't use layout, place it manually
                        p->move(100,100);
                    
                        foo.show();
                    
                        return a.exec();
                    }
                    

                    If you really don't want the layout for some reason here's the version with main window wrapper, but it's not really necessary:

                    #include <QApplication>
                    #include <QPushButton>
                    #include <QMenuBar>
                    
                    struct Foo : public QWidget {
                        QSize sizeHint() const override { return QSize(400,400); }
                    };
                    
                    int main(int argc, char *argv[])
                    {
                        QApplication a(argc, argv);
                    
                        QMainWindow w;
                        w.setMenuBar(new QMenuBar()); //use the built-in layout for menu bar
                        w.menuBar()->addAction("Hi!");
                        w.setCentralWidget(new Foo); //place the widget in built-in layout
                    
                        QPushButton* p = new QPushButton(w.centralWidget());  //place the child manually
                        p->move(100,100);
                    
                        w.show();
                    
                        return a.exec();
                    }
                    
                    H Offline
                    H Offline
                    Harry123
                    wrote on last edited by Harry123
                    #10

                    @Chris-Kawa

                    I tested and this works, but there is a problem with the menubar now obscuring the upper part of the widget.

                    First, this would require modifying all paint functions using absolute coordinates to add a vertical offset equal to the height of the menubar, which is not a simple a job.

                    Second, it requires manually increasing the height of the widget.

                    These entail the kind of assumptions on my part regarding the GUI which I try to avoid. I prefer to let Qt do this kind of calculations, for portability.

                    1 Reply Last reply
                    0
                    • Chris KawaC Offline
                      Chris KawaC Offline
                      Chris Kawa
                      Lifetime Qt Champion
                      wrote on last edited by
                      #11

                      Ok then, you can use the second variant. QMainWindow will do the calculations for you, but...

                      First, this would require modifying all paint functions (...) which is not a simple a job.

                      Actually it's a one-liner:

                      void Widget:: paintEvent(QPaintEvent* evt) {
                          QPainter p(this);
                          p.setTransform(QTransform::fromTranslate(0, layout()->menuBar()->height()));
                          //paint as usual
                      }
                      

                      Second, it requires manually increasing the height of the widget. These entail the kind of assumptions on my part regarding the GUI which I try to avoid.

                      No assumptions needed:

                      QSize sizeHint() const override { return QSize(400, 400 + layout()->menuBar()->height()); }
                      

                      If you're extra paranoid you can also check layout and menubar for nullpointers, but that's not really necessary here.

                      H 1 Reply Last reply
                      2
                      • Chris KawaC Chris Kawa

                        Ok then, you can use the second variant. QMainWindow will do the calculations for you, but...

                        First, this would require modifying all paint functions (...) which is not a simple a job.

                        Actually it's a one-liner:

                        void Widget:: paintEvent(QPaintEvent* evt) {
                            QPainter p(this);
                            p.setTransform(QTransform::fromTranslate(0, layout()->menuBar()->height()));
                            //paint as usual
                        }
                        

                        Second, it requires manually increasing the height of the widget. These entail the kind of assumptions on my part regarding the GUI which I try to avoid.

                        No assumptions needed:

                        QSize sizeHint() const override { return QSize(400, 400 + layout()->menuBar()->height()); }
                        

                        If you're extra paranoid you can also check layout and menubar for nullpointers, but that's not really necessary here.

                        H Offline
                        H Offline
                        Harry123
                        wrote on last edited by Harry123
                        #12

                        @Chris-Kawa

                        I'm learning a lot from your answers, but regarding "No assumptions needed", there is one big assumption here - that the menubar is part of the widget and is displayed on top.

                        I never programmed on the Mac or Android, but I'm not too sure that this assumption will hold there or on all other platforms where Qt was or will be ported.

                        1 Reply Last reply
                        0
                        • Chris KawaC Offline
                          Chris KawaC Offline
                          Chris Kawa
                          Lifetime Qt Champion
                          wrote on last edited by
                          #13

                          @Harry123 said:

                          there is one big assumption here

                          Right. I'm not an expert on other platforms either. I think the menu can indeed not be a part of the window at least on Mac.
                          Ok then. The wrapper option should still be valid in these scenarios.

                          1 Reply Last reply
                          0
                          • mrjjM mrjj

                            @Harry123
                            Good luck.
                            Note.
                            I just added layout to mainwindow and then a widget. ( the green one)
                            So its not directly on centralwidget.

                            H Offline
                            H Offline
                            Harry123
                            wrote on last edited by
                            #14

                            @mrjj

                            You solution works, and works beautifully. And what's more, is probably almost guaranteed to work on all future versions of Qt.

                            So it's a hack, but who cares, as long as it works so well and is so easy to implement.

                            1 Reply Last reply
                            0
                            • N n__c referenced this topic on

                            • Login

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