Changing widgets by replacing layout of a tab run time



  • I am working with tab widget. For a single tab I have more than one widgets. But only one at a time should be there on the tab and user can change that by request to load another widget. To do this I am deleting previous layout of the tab and replacing it with new which contains new widget. The snippet is:

    @delete ui->TabImageProcessing->layout();
    ui->TabImageProcessing->setLayout(mainlayout);@

    But the widgets were still there on the tab. They are not removed. I tried these ways also :

    @if(!ui->TabImageProcessing->layout()->isEmpty())
    {
    for(int i =0;i<n;i++)
    {
    ui->TabImageProcessing->layout()->removeItem(ui->TabImageProcessing->layout()->itemAt(i));
    }
    }@

    It is giving error of accessing null pointer. I am really wandering for the way to replace widget on one tab. Please help.



  • Eureka!!

    @if(!ui->TabImageProcessing->layout()==NULL)
    {
    delete ui->TabImageProcessing;
    ui->TabImageProcessing = new QWidget;
    ui->ToolArea->addTab(ui->TabImageProcessing,"Image Processing");
    }

    ui->TabImageProcessing->setLayout(mainlayout);@



  • Hi,

    @if(!ui->TabImageProcessing->layout()==NULL)@

    I think this line has some flaws:

    " !" operator precedes "==" then: 1.!ui->TabImageProcessing->layout() = 0/false (layout is valid pointer) 2. (0 == NULL) = true ... this is why your code execute but it's wrong ...

    to check a pointer correct is either:
    @if(ui->TabImageProcessing->layout()!=NULL)@

    or

    @if(ui->TabImageProcessing->layout())@

    ... since the layout is an QObject you can get its children:

    @QObject* child;
    foreach(child, layout->children())
    {
    delete child;
    }
    @



  • Thanks for correction Nicu.


  • Moderators

    For QObjects and QWidgets, it's best to use deleteLater(), not delete. If there are any events/signals waiting to be processed when you call delete, your program will crash..



  • [quote author="JKSH" date="1382589695"]For QObjects and QWidgets, it's best to use deleteLater(), not delete. If there are any events/signals waiting to be processed when you call delete, your program will crash..[/quote]

    where to call deleteLater()? The widget should be changed on user's request so I added delete in slot when user make a new request by some signal. will it be fine if i replace delete with deleteLater(). and if no any running dependency found the widget will be deleted immediately ? or it will wait till the app enters in an event loop?

    I found this lines on Qt docs which are puzzling

    The object will be deleted when control returns to the event loop. If the event loop is not running when this function is called (e.g. deleteLater() is called on an object before QCoreApplication::exec()), the object will be deleted once the event loop is started.


  • Moderators

    Yes, replace "delete child" with "child->deleteLater()".

    "Control returns to the event loop" when all current slots return. So, the child will be deleted when all your current slots finish executing.

    [quote author="Tabi" date="1382592374"]I found this lines on Qt docs which are puzzling

    "The object will be deleted when control returns to the event loop. If the event loop is not running when this function is called (e.g. deleteLater() is called on an object before QCoreApplication::exec()), the object will be deleted once the event loop is started." [/quote]See the following example:

    @
    int main (int argc, char *argv[])
    {
    QApplication a(argc, argv);

    QWidget *w = new QWidget();
    w->deleteLater();
    
    doALongOperation();
    
    return a.exec&#40;&#41;;
    

    }
    @

    The lines you quoted mean this: When deleteLater() is called in line 6, event loop hasn't started yet. So, the widget won't be deleted until doALongOperation() returns and the event loop is started in line 10.

    Your situation is not like this though. In your case, your app's event loop has already started when your slot executes.



  • and if you need a direct/immediate deletion?

    bq. QObject::~QObject () [virtual]
    Destroys the object, deleting all its child objects.
    All signals to and from the object are automatically disconnected, and any pending posted events for the object are removed from the event queue. However, it is often safer to use deleteLater() rather than deleting a QObject subclass directly.

    so first I think there is no worry about next signals on this object as they will be disconnected in object destructor ... what about posted events already in the object's queue and waiting to be processed? yes, the object's destructor does not assure events discarding ... but QWidget's destructor? yes, it calls QApplication::removePostedEvents(this) !

    so I believe that

    @
    ...
    delete (QWidget*)child;@

    does the magic!

    which is similar with:

    @
    ...
    QApplication::removePostedEvents(child);
    delete child;
    @

    hope I've not screwed it up ! :)

    Cheers!



  • Thanks for the explanation, I was not aware of this:

    [quote author="NicuPopescu" date="1382617651"]

    @
    ...
    QApplication::removePostedEvents(child)
    delete child;
    @

    [/quote]

    Thanks :)


  • Moderators

    @NicuPopescu, good catch. I wasn't aware of that either :)

    What use case would require an immediate immediate deletion though?



    • when you're in a thread without an event loop and you don't want that QObjects living in that thread to be destroyed when it finishes, having the full control over the appropriate time when this could be done

    -when is not efficient to schedule deletions, being costly to keep alive objects till return to event loop : i.e. for a parent widget you must recreate some children having the same object name as some few scheduled for deletion, and then a style sheet is applied for parent;in this case the style sheet will be parsed and set twice for children having the same name, and moreover I think if they are visible you'll see some ugly things happening on slow platforms(linux embedded)

    as far as I understand the deferred deletion is provided to assure in any circumstances that QObjects to be destroyed just where they live if an event loop is on charge or when threads finish if this is aprropriate only: so it doesn't make really sense when you don't leave the event loop of a thread and can control the time of deletion

    :)


Log in to reply
 

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