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 to Set QMainWindow Size?

How to Set QMainWindow Size?

Scheduled Pinned Locked Moved Unsolved General and Desktop
28 Posts 6 Posters 55.1k 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.
  • B Offline
    B Offline
    bsomervi
    wrote on last edited by
    #11

    To be specific, QWidget::resize() is ignoring the height I set even though the user can resize to that size using the mouse!

    1 Reply Last reply
    1
    • B Offline
      B Offline
      bsomervi
      wrote on last edited by bsomervi
      #12

      Sorry, messed up the repro example with last minute simplifications, this one actually builds and runs:

      #include <QApplication>
      #include <QMainWindow>
      #include <QWidget>
      #include <QTextEdit>
      #include <QVBoxLayout>
      #include <QAction>
      #include <QMenuBar>
      #include <QMenu>
      
      
      class MainWindow
        : public QMainWindow
      {
        Q_OBJECT
      
      public:
        explicit MainWindow ()
          : central_widget_ {new QWidget {this}}
          , edit_ {new QTextEdit {central_widget_}}
          , hideable_edit_ {new QTextEdit {central_widget_}}
          , layout_ {new QVBoxLayout}
          , resize_action_ {new QAction {"&Resize"}}
        {
          setCentralWidget (central_widget_);
          layout_->addWidget (edit_);
          layout_->addWidget (hideable_edit_);
          central_widget_->setLayout (layout_);
          resize_action_->setCheckable (true);
          action_menu_ = menuBar ()->addMenu (tr ("&Action"));
          action_menu_->addAction (resize_action_);
          connect (resize_action_, &QAction::toggled, this, &MainWindow::do_resize);
        }
      
      private:
        Q_SLOT void do_resize (bool checked)
        {
          auto s = size ();
          hideable_edit_->setVisible (!checked);
          if (saved_size_.isValid ())
            {
              // here I want to have the user resizeable main window flipped
              // as if the lower QTextEdit just disappeared/reappeared, i.e. the top
              // QTextEdit remains exactly as is (i.e. as resized by the
              // user resizing the main window)
              //
              // I want the user to be able to move and resize the main
              // window in either state and then the menu action flips
              // between them. It doesn't restore the size if the user
              // shrinks the main window below a certain size.
              resize (saved_size_);
            }
          saved_size_ = s;          // save for when we flip back
        }
      
        QWidget * central_widget_;
        QTextEdit * edit_;
        QTextEdit * hideable_edit_;
        QVBoxLayout * layout_;
        QAction * resize_action_;
        QMenu * action_menu_;
        QSize saved_size_;
      };
      
      int main (int argc, char * argv[])
      {
        QApplication app {argc, argv};
        MainWindow main_window;
        main_window.show ();
        QApplication::connect (&app, &QApplication::lastWindowClosed, &app, &QApplication::quit);
        return app.exec ();
      }
      
      #include "main.moc"
      
      Cobra91151C 1 Reply Last reply
      0
      • B bsomervi

        Sorry, messed up the repro example with last minute simplifications, this one actually builds and runs:

        #include <QApplication>
        #include <QMainWindow>
        #include <QWidget>
        #include <QTextEdit>
        #include <QVBoxLayout>
        #include <QAction>
        #include <QMenuBar>
        #include <QMenu>
        
        
        class MainWindow
          : public QMainWindow
        {
          Q_OBJECT
        
        public:
          explicit MainWindow ()
            : central_widget_ {new QWidget {this}}
            , edit_ {new QTextEdit {central_widget_}}
            , hideable_edit_ {new QTextEdit {central_widget_}}
            , layout_ {new QVBoxLayout}
            , resize_action_ {new QAction {"&Resize"}}
          {
            setCentralWidget (central_widget_);
            layout_->addWidget (edit_);
            layout_->addWidget (hideable_edit_);
            central_widget_->setLayout (layout_);
            resize_action_->setCheckable (true);
            action_menu_ = menuBar ()->addMenu (tr ("&Action"));
            action_menu_->addAction (resize_action_);
            connect (resize_action_, &QAction::toggled, this, &MainWindow::do_resize);
          }
        
        private:
          Q_SLOT void do_resize (bool checked)
          {
            auto s = size ();
            hideable_edit_->setVisible (!checked);
            if (saved_size_.isValid ())
              {
                // here I want to have the user resizeable main window flipped
                // as if the lower QTextEdit just disappeared/reappeared, i.e. the top
                // QTextEdit remains exactly as is (i.e. as resized by the
                // user resizing the main window)
                //
                // I want the user to be able to move and resize the main
                // window in either state and then the menu action flips
                // between them. It doesn't restore the size if the user
                // shrinks the main window below a certain size.
                resize (saved_size_);
              }
            saved_size_ = s;          // save for when we flip back
          }
        
          QWidget * central_widget_;
          QTextEdit * edit_;
          QTextEdit * hideable_edit_;
          QVBoxLayout * layout_;
          QAction * resize_action_;
          QMenu * action_menu_;
          QSize saved_size_;
        };
        
        int main (int argc, char * argv[])
        {
          QApplication app {argc, argv};
          MainWindow main_window;
          main_window.show ();
          QApplication::connect (&app, &QApplication::lastWindowClosed, &app, &QApplication::quit);
          return app.exec ();
        }
        
        #include "main.moc"
        
        Cobra91151C Offline
        Cobra91151C Offline
        Cobra91151
        wrote on last edited by Cobra91151
        #13

        @bsomervi

        Hello!
        You can try to use the restoreGeometry method - https://doc.qt.io/qt-5/qwidget.html#restoreGeometry

        Here is my example (main.cpp):

        #include <QApplication>
        #include <QWidget>
        #include <QMainWindow>
        #include <QPushButton>
        
        int main(int argc, char *argv[])
        {
            QApplication a(argc, argv);
            QMainWindow window;
            window.setWindowTitle("Test MainWindow");
            QWidget widget;
            widget.setMinimumSize(400, 300);
            window.setCentralWidget(&widget);
            QPushButton *testBtn = new QPushButton("Restore size", &window);
            testBtn->setFixedSize(150, 100);
            window.show();
            QByteArray savedGeometry = window.saveGeometry();
            QObject::connect(testBtn, &QPushButton::clicked, [&window, savedGeometry]() {
                if (!savedGeometry.isNull() && !savedGeometry.isEmpty()) {
                    window.restoreGeometry(savedGeometry);
                } else {
                    window.setGeometry(window.geometry().x(), window.geometry().y(), 400, 300);
                }
            });
            return a.exec();
        }
        

        Result:

        Restore geometry example

        Happy coding!

        1 Reply Last reply
        0
        • B Offline
          B Offline
          bsomervi
          wrote on last edited by
          #14

          Sure I have tried using (save|restore)Geometry() they have exactly the same issue. If you can make them work with my example then I would be delighted, but I've had no luck.

          Cobra91151C 1 Reply Last reply
          0
          • B bsomervi

            Sure I have tried using (save|restore)Geometry() they have exactly the same issue. If you can make them work with my example then I would be delighted, but I've had no luck.

            Cobra91151C Offline
            Cobra91151C Offline
            Cobra91151
            wrote on last edited by
            #15

            @bsomervi

            I have tried your code, fixed a few compile errors, but for me it works well.

            Result:
            Restore example

            What are you trying to achieve? By the way, you can use QSplitter https://doc.qt.io/qt-5/qsplitter.html with layout to hide the hideable_edit_ (QTextEdit).

            Also, there are two options you can try:

            1. Use QResizeEvent https://doc.qt.io/qt-5/qresizeevent.html
            2. Use nativeEvent https://doc.qt.io/qt-5/qwidget.html#nativeEvent to intercept and handle the resize/restore window messages (https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-size, https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-sizing)
            1 Reply Last reply
            0
            • B Offline
              B Offline
              bsomervi
              wrote on last edited by bsomervi
              #16

              The problem is when the single widget rendering is shrunk using the mouse to the minimum size toggling the action twice does not restore the main window size. I can find no way to set the size of the main window as small as it was settable using the mouse. This is a problem (a) because there seems to be no way to do in code what can be done with the mouse, and (b) the whole point is to have a "view" of the main window set by the user that can be returned to using the code. Users simply cannot believe we can't do this and their chosen size is ignored.

              1 Reply Last reply
              0
              • B Offline
                B Offline
                bsomervi
                wrote on last edited by bsomervi
                #17

                native events are no use to us as our application is portable. How do i use resizeEvents to do this? Note that my real case has a whole bunch of widgets and layouts in the hideable part, I don't think a splitter is appropriate as the bottom part is not resizable. I just used another QTextEdit in my example above as the header was already included.

                Cobra91151C 1 Reply Last reply
                0
                • B Offline
                  B Offline
                  bsomervi
                  wrote on last edited by
                  #18

                  @Cobra91151 where are the compile errors in my code example?

                  You second animation above clearly shows the issue I am trying to solve.

                  How do I make use of an override resizeEvent() to fix this issue? I don't see how it can help, a resize Event is triggered by some external action, how can I make it fix the specific when a call to MainWindow::resize() does not do what it is asked to do?

                  Cobra91151C 1 Reply Last reply
                  0
                  • B bsomervi

                    native events are no use to us as our application is portable. How do i use resizeEvents to do this? Note that my real case has a whole bunch of widgets and layouts in the hideable part, I don't think a splitter is appropriate as the bottom part is not resizable. I just used another QTextEdit in my example above as the header was already included.

                    Cobra91151C Offline
                    Cobra91151C Offline
                    Cobra91151
                    wrote on last edited by
                    #19

                    @bsomervi

                    What do you mean portable? I suppose your app must run on different operating systems? If so, then check out this link: https://forum.qt.io/topic/104533/how-to-ignore-the-event-when-i-click-on-the-button-to-maximize-the-window-windowmaximizebuttonhint/9

                    You can use nativeEvent with defines for different operating systems and add the appropriate code.

                    1 Reply Last reply
                    0
                    • B bsomervi

                      @Cobra91151 where are the compile errors in my code example?

                      You second animation above clearly shows the issue I am trying to solve.

                      How do I make use of an override resizeEvent() to fix this issue? I don't see how it can help, a resize Event is triggered by some external action, how can I make it fix the specific when a call to MainWindow::resize() does not do what it is asked to do?

                      Cobra91151C Offline
                      Cobra91151C Offline
                      Cobra91151
                      wrote on last edited by Cobra91151
                      #20

                      @bsomervi

                      As for compile errors: you forgot to add & in two connects. Example below:

                      Your code:
                      connect(resize_action_, QAction::toggled, this, &MainWindow::do_resize);
                      QApplication::connect(&app, QApplication::lastWindowClosed, &app, QApplication::quit);

                      Fixed:
                      connect(resize_action_, &QAction::toggled, this, &MainWindow::do_resize);
                      QApplication::connect(&app, &QApplication::lastWindowClosed, &app, QApplication::quit);

                      1 Reply Last reply
                      1
                      • B Offline
                        B Offline
                        bsomervi
                        wrote on last edited by
                        #21

                        Ha! OK on compile errors. My compiler I used for test doesn't pick that up and works (MinGW 8.1). They are indeed errors.

                        1 Reply Last reply
                        0
                        • B Offline
                          B Offline
                          bsomervi
                          wrote on last edited by bsomervi
                          #22

                          OK, so here's another related frustration. My real code persists the state of the checkable action into a settings file. On startup it builds the UI and then if the action is checked hides the lower widget(s). This is all in the main window constructor. It then goes on to restore the reduced size main window using MainWindow::restoreGeometry(geometry) also from the settings file stored at shutdown with QMainWindow::saveGeometry(). This shows the correctly sized main window. If I then toggle the action twice the main window size then is bigger. This is really annoying. Why does MainWindow::restoreGeometry() work in the constructor before the first QMainWindow::show() and yet after that neither MainWindow::restoreGeometry(), nor QMainWindow::resize(), nor any other way of trying to set the size, I have tried so far, work correctly.

                          I have tried removing the lower widget(s) from the layout. I have tried hiding the whole main window before making the size adjustments and showing again afterwards (although I guess this is a no-op as i don't get into the event loop between the calls).

                          I must be missing the necessary incantation to make these sizing member functions work correctly.

                          1 Reply Last reply
                          0
                          • B Offline
                            B Offline
                            bsomervi
                            wrote on last edited by
                            #23

                            @Cobra91151 Note also that this misbehaviour is the same on Windows, Linux, and macOS, so I don't think it is anything to do with native control renderings. It is something in Qt that is causing hidden widgets to influence the minimum size of a window when they should not.

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

                              Hidden widgets are not used by the sizeHint() calculation. Still no example which shows the opposite.

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

                              1 Reply Last reply
                              0
                              • B Offline
                                B Offline
                                bsomervi
                                wrote on last edited by bsomervi
                                #25

                                @Christian-Ehrlicher why is no one seeing this issue?

                                • Build my example above.
                                • Run it.
                                • Click the checkable menu item to move to the single widget display.
                                • Shrink the window to its minimum size using the mouse.
                                • Click the checkable menu item to move to the dual widget display.
                                • Click it again to move back to the smaller single widget display.

                                At this point the window is larger that it was shrunk to before. Why? The code calls resize with the smaller size but Qt still somehow accounts for the hidden widget. MainWIndow::restoreGeometry() does the same.

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

                                  Ok, it took a while to understand what's going on here.
                                  When you hide the widget, the main window as it's parent still has the old minimum height set which includes the (now hidden) widget. Therefore you can't resize the main window to the smaller saved size. You have to wait until the main window is notified about the hidden widget and it's minimum size is adjusted.

                                  void do_resize (bool checked)
                                  {
                                    auto s = size ();
                                    hideable_edit_->setVisible (!checked);
                                    qDebug() << "Current minimum size:" << minimumHeight() << saved_size_;
                                    if (saved_size_.isValid ())
                                    {
                                        desired_size_ = saved_size_;
                                    }
                                    saved_size_ = s;          // save for when we flip back
                                  }
                                  
                                  bool event(QEvent *e) override
                                  {
                                    auto ret = QMainWindow::event(e);
                                    if (e->type() == QEvent::LayoutRequest) {
                                      if (desired_size_.isValid()) {
                                        auto s = desired_size_;
                                        desired_size_ = QSize();
                                        resize(s);
                                      }
                                    }
                                    return ret;
                                  }
                                  QSize desired_size_;
                                  

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

                                  1 Reply Last reply
                                  2
                                  • B Offline
                                    B Offline
                                    bsomervi
                                    wrote on last edited by
                                    #27

                                    Thanks for taking the time to work that out @Christian-Ehrlicher, it works perfectly with restoring the size and also with restoring the whole window geometry which was my actual use case. I knew there would be an incantation that did this but finding it would have taken me a lot longer than the attempts I had made so far.

                                    Looks to me that the Qt logic should be either giving higher priority to resize invocations, or it should be deferring the actual resize until after the layout change has been done. I'll bet it is a nasty chicken and egg, which comes first, situation.

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

                                      The problem is the OS - until the OS does not tell us that the widget is really hidden or resized we have to wait. And all this stuff is async.

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

                                      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