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

Resizing main widget after removal the internal widget



  • I can’t figure out, why i can’t resize my main widget right after removing the internal widget? And how to make resizing work? Could please you tell me? I wrote an example:

    #include <QApplication>
    #include <QHBoxLayout>
    #include <QWidget>
    #include <QGroupBox>
    #include <QTimer>
    #include <QObject>
    
    int main(int argc, char *argv[]) {
    	QApplication a(argc, argv);
    
    	QWidget* main = new QWidget;
    
    	QGroupBox* widget1 = new QGroupBox("Widget 1");
    	QGroupBox* widget2 = new QGroupBox("Widget 2");
    	widget1->setFixedSize(400, 250);
    	widget2->setFixedSize(400, 250);
    
    	QHBoxLayout* grid_layout = new QHBoxLayout;
    	grid_layout->addWidget(widget1);
    	grid_layout->addWidget(widget2);
    
    	main->setLayout(grid_layout);
    	main->show();
    
    	QTimer::singleShot(3000, [&](){
    		delete widget2;
    		main->resize(1, 1); // <-------------| Does not works
    	});
    	QTimer::singleShot(5000, [&](){
    		main->resize(1, 1); // <-------------| Works
    	});
    	return a.exec();
    }
    

    Something like this freezes the program

    QTimer::singleShot(3000, [&](){
    		delete widget2;
    		while (main->size() != QSize(1, 1))
    			main->resize(QSize(1, 1));
    	});
    

  • Lifetime Qt Champion

    Hi
    When you remove something from a layout a re-calculation event is put on the event
    queue. So its asynchronous as seen if you do

     QTimer::singleShot(3000, [&](){
            delete widget2;
            a.processEvents();  // allow it to process the events from "delete"
            main->resize(1, 1); // <-------------| Does not works
        });
    

    then resize works. However, using processEvents() is not recommended but you can use a single shot for the
    resize and it will work too.



  • @mrjj , @nammidd
    Are you sure you can just delete a widget on a layout without telling the layout about it? I thought you need to go something like:

    grid_layout->removeWidget(widget2);
    widget2->deleteLater();
    

    ?


  • Lifetime Qt Champion

    @JonB
    Hi
    Yes you are right that the correct way
    is to use removeWidget or takeAt.
    But apparently plain delete also seems to work, i would guess due to the internal
    qobject housekeeping notifications.
    But very good point!



  • @mrjj
    Looking at the code for QLayout::removeWidget(QWidget *widget) at https://code.woboq.org/qt5/qtbase/src/widgets/kernel/qlayout.cpp.html#_ZN7QLayout12removeWidgetEP7QWidget it does:

    delete takeAt(i);
    invalidate();
    

    so it invalidate()s the layout, which update()/redraws it, which might be good here to get main redrawn/resized correctly?


  • Lifetime Qt Champion

    @JonB
    Good digging :)
    Well i did try to call invalidate but in this case, the result was the same.


Log in to reply