简体   繁体   中英

Qt QWidget::minimumSizeHint delay

I want to write dialog with "spoiler". When I show/hide some elements, the form must resize to match her content. But I noticed that minimumSizeHint works with some delay. For example I wrote following dialog code:

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>

class Dialog : public QDialog {
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);

private:
    QPushButton *button1, *button2, *button3;
    void adjust();
};

#endif // DIALOG_H

dialog.cpp

#include <QVBoxLayout>
#include <QPushButton>
#include <QTimer>

#include "dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent) {
    QVBoxLayout *layout = new QVBoxLayout;
    button1 = new QPushButton("bad method", this);
    button2 = new QPushButton("working method", this);
    button3 = new QPushButton("indent", this);
    layout->addWidget(button1);
    layout->addWidget(button2);
    layout->addWidget(button3);
    setLayout(layout);

    connect(button1, &QPushButton::pressed, [=]() {
        button3->setVisible(!button3->isVisible());

        adjust();
    });

    connect(button2, &QPushButton::pressed, [=]() {
        button3->setVisible(!button3->isVisible());

        QTimer *timer = new QTimer(this);
        connect(timer, &QTimer::timeout, [=](){ adjust(); });
        timer->setSingleShot(true);
        timer->start(0);
    });
}

void Dialog::adjust() {
    resize(width(), minimumSizeHint().height());
}

When pressed button1, the form isn't match her content tightly, but when pressed button2, the form tightly match her content. How to achieve results as pressing button2 without timers and other workarounds? Why button1 isn't work?

Consider that the minimum size is not computed until some events are processed in the event loop. If you don't want to use a timer, one workaround is to process the event loop for some iterations after the button is hidden or made visible, and then adjust size.

It's like :

        button3->setVisible(!button3->isVisible());

        for(int i=0;i<10;i++)
           qApp->processEvents();

        adjust();

A better solution is to call QLayout::activate() before resizing:

        button3->setVisible(!button3->isVisible());

        layout->activate();

        adjust();

activate() forces your layout to recalculate the size hint.

I tried the QLayout::activate() solution, but it doesn't work for me.

QLayout::activate() returns false .

This is my code: this is a QMainWindow .

ui.groupBox->setVisible(!ui.groupBox->isVisible());

qDebug() << this->layout()->activate();

qDebug() << this->minimumSizeHint();

this->resize(this->minimumSizeHint());

any ideas why it's not working?

My current workaround is:

QTimer::singleShot(10, this, SLOT(on_resizeMin()));

but i noticed 10ms may not be enough on a slow system. Nasty workaround.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM