Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

showMaximized doesn't update geometry immediately



  • Hi, I noticed that showFullScreen function immediately updates geometry of the main window, but when showMaximized is used then it happens later for some reason.

    Testing code with "showFullScreen":

    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        showFullScreen();
        updateGeometry();
        qDebug() << "main window geometry immediately after showFullScreen = " <<  geometry();
        QTimer::singleShot(1000, [&](){
           qDebug() << "main window geometry 1 second after showFullScreen = " <<  geometry();
        });
    }
    
    // main window geometry immediately after showFullScreen =  QRect(1366,0 1600x900)
    // main window geometry 1 second after showFullScreen =  QRect(1366,0 1600x900)
    

    Testing code with "showMaximized":

    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        showMaximized(); //showFullScreen();
        updateGeometry();
        qDebug() << "main window geometry immediately after showMaximized = " <<  geometry();
        QTimer::singleShot(1000, [&](){
           qDebug() << "main window geometry 1 second after showMaximized = " <<  geometry();
        });
    }
    
    // main window geometry immediately after showMaximized =  QRect(1766,130 800x600)
    // main window geometry 1 second after showMaximized =  QRect(1366,23 1600x837)
    

    Is there any way to force immediate update of geometry?
    I'd like to avoid using "QTimer::singleShot" just to fix this problem.


  • Moderators

    Don't call showXXX() in the constructor. That's not a proper place for that. A widget should be shown by whoever created it not by the widget itself.

    How long it takes to show a widget is platform specific. OS, window manager and several other factors come to play here. Whenever that happens your widget will get a showEvent(). This is the first place you can query the widget for its geometry. Anywhere before that you won't get a result you're looking for.



  • Thank you for the reply.

    In main.cpp I have

    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.showMaximized();
        return a.exec();
    }
    

    In mainwindow.cpp I have:

    void MainWindow::showEvent(QShowEvent *event)
    {
        qDebug() << "MainWindow::showEvent geometry() = " << geometry();
    }
    

    But it still outputs the old (not maximized) geometry when the program is started...
    It outputs correct geometry only if I use "w.showFullScreen()" instead of "w.showMaximized()".

    I also checked the following:

    void MainWindow::changeEvent(QEvent* e)
    {
       if (e->type() == QEvent::WindowStateChange)
       {
          QWindowStateChangeEvent* ev = static_cast<QWindowStateChangeEvent*>(e);
          if (!(ev->oldState() & Qt::WindowMaximized) && windowState() & Qt::WindowMaximized)
          {
            qDebug() << "MainWindow::changeEvent geometry() = " << geometry();
          }
       }
       QWidget::changeEvent(e);
    }
    

    And it also outputs the not-maximized geometry at the start of the program.



  • It looks like similar issue was posted at:
    https://stackoverflow.com/questions/16552495/qmainwindowshowmaximized-doesnt-update-size

    Currently the workaround that seems to work for me is to call "showFullScreen" before "showMaximized" and catch it once within "resizeEvent" or "showEvent".

    void MainWindow::resizeEvent(QResizeEvent *event)
    {
        static bool initial_resize_done = false;
        if (!initial_resize_done) {
            initial_resize_done = true;
            qDebug() << "MainWindow::resizeEvent initial resize geometry() = " << geometry();
        }
    }
    

    But that's not elegant...

    Btw I tested the code below:

    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
    
        w.showFullScreen();
        w.geometry(); // returns correct geometry
        w.showMaximized();
        w.geometry(); // returns incorrect geometry (it's not fullscreen/maximized)
        return a.exec();
    }
    

    It appears that the first call to geometry (after showFullScreen) is returning fullscreen/maximized size, and the 2nd call (after showMaximized) is returning smaller size for some reason. So the problem is not only about the geometry being updated late, it's also about geometry being reverted to some other value before being updated.



  • @michalmonday
    You may be right and there is a problem somewhere here. But I would only expect the geometry to get updated during an event later, not immediately after showMaximized(). The fact that showFullScreen() does update immediately is "an accident".

    In your MainWindow::showEvent() you do not call the base class implementation, and in your MainWindow::changeEvent() you only call it after you have printed out the geometry. In both cases I would put the base class call first, and only then look at geometry, does that make any difference?



  • @JonB
    Thank you for reply and the suggestion. I made the following changes:

    void MainWindow::resizeEvent(QResizeEvent *event)
    {
        QMainWindow::resizeEvent(event); // added
    
    void MainWindow::changeEvent(QEvent* e)
    {
       QWidget::changeEvent(e); // moved from the end to start of function
    

    and tested again but still, when the program is started, the geometry is not of a maximized window.

    Btw I reimplemented "event" method and printed type/geometry like:

    bool MainWindow::event(QEvent *event)
    {
        QMainWindow::event(event);
        qDebug() << GetTickCount() << " - " << event->type() << geometry();
    }
    

    It appears that when the program starts (and showMaximized is used), the 2nd "resize" and 3rd "move" events are responsible for setting geometry to maximized values.
    alt text

    Looking at these logs, at program startup, unfortunately there's not a single event that would happen for the first time when the geometry is already updated...

    Btw my main goal is to use QGraphicsView::centerOn() when program is launched. To make my graphics item appear in the center of the graphics view, which currently does not work like it should because it is applied when geometry of the view is not updated to maximized value.

    Edit:
    I made some more tests, calling "windowHandle()->geometry()" returns correct geometry few events before "geometry()" does. It's still not immediate but at least there is a "showToParent" event which happens to output correct geometry when it happens for the first time. So the following workaround could be done:

    bool MainWindow::event(QEvent *event)
    {
        static bool initial_geometry_checked = false;
        if (!initial_geometry_checked && event->type() == QEvent::ShowToParent) {
            if (QWindow *window = windowHandle()) {
                initial_geometry_checked = true;
                qDebug() << "initial geometry = " << window->geometry();
                qDebug() << "incorrect geometry = " << geometry();
            }
        }
        return QMainWindow::event(event);
    }
    

    which outputs the following when program is started:

    initial geometry =  QRect(1366,23 1600x837)
    incorrect geometry =  QRect(1766,130 800x600)
    

Log in to reply