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

QProgressDialog: doesn't "relayout" when showing?



  • both mac and win have same behavior.

    if i call setMinimumWidth() or setSize() before the window is shown (haven't tested after), then, when the window IS shown, the layout is wrong, like this (squashed to the top): (i hid the cancel button)

    0_1552275879141_Screen Shot 2019-03-10 at 8.30.54 PM.png

    but if i touch the edge of the window with the mouse (causing a resize event) everything snaps correctly into place (pleasing vertical distribution):

    0_1552275941197_Screen Shot 2019-03-10 at 8.32.37 PM.png

    even if i call updateGeometry() after i call show(), it doesn't help.



  • okay the problem was my hiding the cancel button with i_qDlg.setCancelButton(NULL);

    i guess i expected that to cause a relayout of the geometry, or post a styleChange event, but alas no.

    so all i did was then immediately call QCoreApplication::postEvent(i_qDlg, new QEvent(QEvent::StyleChange)); and all is well.

    thanks all for the hints and tips! (this actually sounds like a bug but whatever)

    -dave


  • Moderators

    Call updateGeometry on the problematic child, I believe this is a bug. Here's an excerpt from one of my custom widgets:

    
    void StatusWidgetPrivate::update()
    {
        Q_Q(StatusWidget);
        if (statusList.size() == 0)  {
            q->setVisible(false);
            return;
        }
        else
            q->setVisible(true);
    
        // ... Some irrelevant code ...
    
        // TODO [BUG]: Write bugreport
        // Calling `updateGeometry()` shouldn't be necessary, but the parent doesn't `adjustSize()` properly without it.
        q->updateGeometry();
    
        emit q->changed();
    }
    

    And here's how I connected it (just for context):

    QObject::connect(ui.statusWidget, &StatusWidget::changed, this, &QDialog::adjustSize);
    


  • sorry, i'm still new to this, so code fragments are more opaque to me than you might expect.

    i have a QProgressDialog that i am NOT overriding, ie: i'm using it without subclassing it. the entire contents of the dialog need to be re-laid out, not just one widget. how do i do that? i also don't know what a statuswidget is


  • Moderators

    @davecotter said in QProgressDialog: doesn't "relayout" when showing?:

    i have a QProgressDialog that i am NOT overriding, ie: i'm using it without subclassing it.

    This is fine, no reason to subclass if you don't need to.

    the entire contents of the dialog need to be re-laid out, not just one widget. how do i do that?

    Is it made in the designer? If so could you screenshot the object tree from the designer (right side) and say which widget you're hiding?

    i also don't know what a statuswidget is

    That's a custom widget I wrote for a project. I pasted the code as an illustration only. The widget is hidden/shown based on some unimportant condition. The point is that the dialog that holds it, however, doesn't resize properly if I don't call updateGeometry on this child widget. As I said, I believe this is a bug in the layout/widget system, where the geometry change isn't completely propagated up through the object tree.


  • Moderators

    @davecotter
    I‘ve run into this as well.

    Am I right in the assumption, that you call resize or setGeometry on your ProgressDialog and eventually show?

    Simply call show first and set the geometry/size afterwards.

    Should fix the issue.



  • Is it made in the designer?

    no it's QProgressDialog

    Simply call show first and set the geometry/size afterwards

    i did attempt to call qDialog.show() and then call qDialog.updateGeometry(), that didn't help, it still showed with wrong geometry.


  • Moderators

    @davecotter said in QProgressDialog: doesn't "relayout" when showing?:

    no it's QProgressDialog

    Humor me, will you?

    QCoreApplication::postEvent(progressDialog, new QEvent(QEvent::StyleChange));
    

    where progressDialog is a pointer to your dialog. Does this work?
    I saw many a thing in the source and almost none was even remotely appealing ...



  • calling that after calling show() does nothing. even after calling show() then QApplication::processEvents(), still nothing. only AFTER the window is already on the screen (showing bogus geometry) does this call do anything (and yes it corrects the geometry), but doing it this way causes ugly visual flicker

    what gives? how me fixy? layout should work even when the window is still hidden.


  • Moderators

    @davecotter
    Ok, I'm kind uncomfortable suggesting this...

    You could, as a work around, position your progressDialog way of screen, resize it and move it to the position i'ts supposed to be.

    It's ugly, it's hacky but it should remove the flickering issue. However it will not solve the underlying issue.

    To you happen to have a minimal workable example ?


  • Moderators

    @davecotter said in QProgressDialog: doesn't "relayout" when showing?:

    how me fixy?

    Well, my best guess now is to wait for the polish event (with an event filter) and post the style change event into the event loop. Bad and ugly.

    layout should work even when the window is still hidden.

    Yes, if the progress dialog used a QLayout, which it doesn't. It recalculates its own children's positions, it's a big mess in there ...



  • okay the problem was my hiding the cancel button with i_qDlg.setCancelButton(NULL);

    i guess i expected that to cause a relayout of the geometry, or post a styleChange event, but alas no.

    so all i did was then immediately call QCoreApplication::postEvent(i_qDlg, new QEvent(QEvent::StyleChange)); and all is well.

    thanks all for the hints and tips! (this actually sounds like a bug but whatever)

    -dave


  • Moderators

    @davecotter said in QProgressDialog: doesn't "relayout" when showing?:

    this actually sounds like a bug

    Almost certainly, yes.


Log in to reply