Removing widgets from layout without destroying them



  • I'm using a QTabWidget to display various data. This data is contained in classes that are derived from QWidget. As I have several versions of the same data ( for several different years ), I want to be able to swap the displayed version. I use a QComboBox to call a method that does that for me. On construction, I create my data and put one of the widgets into my tabWidget:

    @
    // during construction
    MyData *firstData, *secondData; // MyData is a custom class, derived from another virtual custom class that derives from QWidget
    firstData = new MyData();
    secondData = new MyData();
    // do some parameterisation
    // ...
    _allData->append(firstData); // _allData is a QList that stores all different versions of my data
    _allData->append(secondData);

    _ui->dataLayout->addWidget( _allData->at(_allData->count() -2)); // dataLayout is the layout of one of the tabs of my tabWidget. This complicated way of adding the correct widget has it's background. I know I could simply append firstData, but I need to be flexible if I want to have more versions of my data.

    @

    So far so good. This works without a problem for all different tabs I use.

    I then have a comboBox that calls a slot named 'changeYear' on the signal 'currentIndexChanged(QString)'. This slot looks like this:

    @
    void MyClass:changeYear(QString year) {

    int displayYear = year.toInt()
    
    _ui->dataLayout->takeAt(0);    // I would expect this to remove the QLayoutItem that encapsulates my Data from the Layout.
    //_ui->dataLayout->update();     this doesn't work either - makes no difference.
    
    // add the correct widget
    for ( int i = 0; i < _allData->count(); ++i ) {
        if ( _allData->at(i)->year() == displayYear ) {        // Data->year() returns an int I use to identify which version of my Data this is
            _ui->dataLayout->addWidget(_allData->at(i));
            break;
        }
    }
    

    }

    @

    The slot gets called correctly and the for-loop correctly identifies the new data I want to add to my layout. However, takeAt() doesn't remove the old widget. This leads to having both Widgets in my layout at once, which, of course, doesn't quite work.

    I know I can do:
    @

    QLayoutItem *thisItem = _ui->dataLayout->takeAt(0);
    delete thisItem->widget();

    @

    to get rid of it. That, however, doesn't help me, as I don't want to destroy my data. This is not up for discussion.
    However, whatever I tried to only remove the Widget from my layout, it didn't work. I could simply add all my Data Widgets to my layout and hide() and show() accordingly, but this causes extra headache for all my signals and slots I'd have to take care of. Also, why would I want to do that in the first place?

    Any chance I can just remove my Widget from the layout without having to destroy it?



  • "QLayout::removeWidget":http://qt-project.org/doc/qt-4.8/qlayout.html#removeWidget

    bq. Removes the widget from the layout.



  • Yeah well, I should've said that I tried removeWidget and removeItem as well to no avail. The widget I want to remove simply still shows.



  • Yes, but the doc say:

    bq. After this call, it is the caller's responsibility to give the widget a reasonable geometry

    So ... just hide it, or give it a reasonable geometry if you want it to be still visible :-)



  • Well, I'd have expected a widget that is not part of any layout wouldn't be displayed anyways, but I guess that's my fault then.

    Thank you for pointing out my error here.



  • you could also try using "QStackedLayout":http://qt-project.org/doc/qt-4.8/qstackedlayout.html



  • I've commonly used this approach to create simple list-like UI:

    @void QtPropertyGenerator::addProperty() {
    Widget p = new Widget(this);
    ui->pLayout->addWidget(p);
    properties.append(p);
    connect(p, SIGNAL(deleteMe(Widget
    )), this, SLOT(deleteProperty(Widget*)));
    }

    void QtPropertyGenerator::deleteProperty(Widget *p) {
    ui->pLayout->removeWidget(p);
    properties.removeOne(p);
    p->deleteLater();
    }@

    Just remove the deleteLater() line and remember to hide the widget because it will show without the layout.


Log in to reply
 

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