When to set initial position of a toplevel QWidget?



  • I am wondering when to set the initial position for a top-level QWidget, which has it's size calculated by it's contents (it's layout).

    I want to center the widget on the primary screen. On the one hand, I must wait until the layout has finished calculating the size, on the other, I need a location where the positioning will only happen once.

    In the constructor, the size is not yet correct, even if I manually activate the layout.
    The resize event can potentially arrive multiple times, e.g. on user action. The show event likewise.

    Is there any signal or method I could reimplement that basically tells the the initial layouting of the widget is done?



  • "QWidget::adjustSize()":http://qt-project.org/doc/qt-4.8/qwidget.html#adjustSize should do the trick.
    @
    class Widget : public QWidget
    {
    Q_OBJECT

    public:
    Widget(QWidget *parent = 0) : QWidget(parent)
    {
    QWidget *widgetA = new QWidget;
    widgetA->setFixedSize(300, 200);

        QWidget *widgetB = new QWidget;
        widgetB->setFixedSize(300, 200);
    
        QHBoxLayout *layout = new QHBoxLayout;
        layout->addWidget(widgetA);
        layout->addWidget(widgetB);
    
        setLayout(layout);
    
        adjustSize();
    
        QRect availableGeometry(QApplication::desktop()->availableGeometry());
        move((availableGeometry.width() - width()) / 2,
             (availableGeometry.height() - height()) / 2);
    }
    

    };
    @
    Brain to terminal. Not tested. Exemplary.



  • Looks promising. Thanks!



  • Nope, adjustSize() seems to do nothing when running in the constructor.



  • The best solution I could come up with is to reimplement the resizeEvent, but only set my window position the first time I get there (after that, I set a flag that my initial positioning is finished).

    Oddly complicated for something as simple as setting the initial widget position.



  • How about to implement single shot timer with 0 msec in constructor and connect to something "initWidget" slot ?
    @
    void initWidget()
    {
    // center widget
    }
    @

    and in constructor, last line ...
    @
    QTimer::singleShot(0, this, SLOT(initWidget));
    @



  • [quote author="Asperamanca" date="1331885932"]Nope, adjustSize() seems to do nothing when running in the constructor.[/quote]
    Well, I've tried the example and it works as expected (Qt 4.8, Windows, MinGW). Before the call to adjustSize() the widget has the default size of 640, 480; after the call it has a size of 628, 222, which is the size of the child widgets plus the content margin and spacing of the layout.

    Have you set the layout to the widget before calling adjustSize()?
    Do you use heavily nested layouts?
    Do you add information to the widgets (for example text to a label) which alters the size of some child widgets after it has been constructed (and centered)?

    Can you provide a small, compilable example that reproduces your problem?



  • Well, I am using 4.7.3, so maybe it's fixed in 4.8.0

    My initialization order looks like this:

    @ setCentralWidget(new QWidget());

    // m_pMainLayout is a QBoxLayout*
    m_pMainLayout->setSpacing(5);
    m_pMainLayout->setContentsMargins(0,0,0,0);
    centralWidget()->setLayout(m_pMainLayout);
    // m_pPictureViewer is a custom QGraphicsView subclass
    m_pMainLayout->addWidget(m_pPictureViewer);
    

    // m_pHardwareKeypad is a QLabel subclass
    m_pMainLayout->addWidget(m_pHardwareKeypad,
    0, Qt::AlignCenter);

    m_pPictureViewer->setFixedSize(800,480);
    
    adjustSize();
    // Size should now be at least 800x480, but it is still 640x480
    

    @



  • I can confirm that the following piece of code works for 4.8.0 and 4.7.3.
    @
    class MainWindow : public QMainWindow
    {
    Q_OBJECT

    public:
    MainWindow(QWidget *parent = 0) : QMainWindow(parent)
    {
    setCentralWidget(new QWidget());

        // m_pMainLayout is a QBoxLayout*
        QVBoxLayout *m_pMainLayout = new QVBoxLayout;
    
        m_pMainLayout->setSpacing(5);
        m_pMainLayout->setContentsMargins(0,0,0,0);
    
        centralWidget()->setLayout(m_pMainLayout);
    
        // m_pPictureViewer is a custom QGraphicsView subclass
        QGraphicsView *m_pPictureViewer = new QGraphicsView;
    
        m_pMainLayout->addWidget(m_pPictureViewer);
    
        // m_pHardwareKeypad is a QLabel subclass
        QLabel *m_pHardwareKeypad = new QLabel;
    
        m_pMainLayout->addWidget(m_pHardwareKeypad,
                                 0, Qt::AlignCenter);
    
        m_pPictureViewer->setFixedSize(800, 480);
    
        qDebug() << width() << height();   // 640, 480
    
        adjustSize();
    
        qDebug() << width() << height();   // 800, 498
    }
    

    };
    @
    What happens if you replace your custom classes with their Qt base classes (QGraphicsView and QLabel)?

    The best thing would be a small, compilable example that reproduces your problem.



  • I must have made a mistake, because it worked when I retried it today. Thanks a lot!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.