PDA

View Full Version : Updating widgets



The 11th plague of Egypt
18th September 2011, 20:01
I have a pointer to a QGroupBox. I want to destroy the QGroupBox, create a new one and have the pointer look for the new one.

If I try to use this code, the QGroupBox simply disappears. I need to update it, and deleting->recreating it is the simplest way I can think of.

QGroupBox *oldReceivedPMsBox = receivedPMsBox;

receivedPMsBox = new QGroupBox("Received PMs", this);
myMessageScrollList = new MessageScrollList(account->getUser()->getReceivedPMs(), this);
QVBoxLayout *receivedPMsLayout = new QVBoxLayout;
receivedPMsLayout->addWidget(myMessageScrollList);
receivedPMsBox->setLayout(receivedPMsLayout);

oldReceivedPMsBox->deleteLater();

Please help me.

norobro
18th September 2011, 21:41
Think about what "oldReceivedPMsBox" is pointing at and where you're calling deleteLater().


I need to update it, and deleting->recreating it is the simplest way I can think of.

Kind of a brute force way of updating, don't you think? Can you not clear "myMessageScrollList"?

The 11th plague of Egypt
21st September 2011, 14:56
Yes, I solved using this code. I hope it destroys all the widgets in myMessageScrollList, will check.
Tell me if it's correct on the GUI side, please.

QGroupBox *oldReceivedPMsBox = receivedPMsBox;

receivedPMsBox = new QGroupBox("Received PMs", this);
myMessageScrollList = new MessageScrollList(account->getUser()->getReceivedPMs(), this);
QVBoxLayout *receivedPMsLayout = new QVBoxLayout;
receivedPMsLayout->addWidget(myMessageScrollList);
receivedPMsBox->setLayout(receivedPMsLayout);

myLayout->removeWidget(oldReceivedPMsBox);
oldReceivedPMsBox->deleteLater();
myLayout->addWidget(receivedPMsBox, 0, 0);
myMessageScrollList is a scrollarea full of MessageWidgets, so I need to destroy a bunch of objects anyway.
Is there something inherently wrong in destroying widgets at runtime?

BTW I have a question about QGroupBox


messagesBox = new QGroupBox("title", this);
QWidget *widgetInABox = new QWidget;
QVBoxLayout *boxLayout = new QVBOXLayout;
boxLayout->addWidget(widgetInABox);
messagesBox->setLayout(boxLayout);
Does widgetInABox become a child of messagesBox?

wysota
21st September 2011, 17:42
Why are you creating a new groupbox instead of reusing the old one?

The 11th plague of Egypt
21st September 2011, 18:34
Because it's quicker?

To be honest, this is a little more complex. That's not the whole code.

I have a QGroupBox, inside the layout of which is a QScrollArea.

Inside the QScrollArea is a QWidget.

Inside the QWidget is layout which holds a whole bunch of QWidgets, some of which I need to remove.

The new code destroys the QWidget inside the QScrollArea, and leaves the QGroupBox intact.

I don't know if using deletelater() on the QWidget destroys all the QWidgets inside its layout.

Here's the whole thing

MessageScrollBox::MessageScrollBox(const QString &_title, const QVector<Message*> *messages, QWidget *parent) :
QWidget(parent), title(_title), myMessages(messages)
{
QVBoxLayout *containerLayout = new QVBoxLayout;

for (QVector<Message*>::const_iterator it = myMessages->constBegin(); it != myMessages->constEnd(); ++it)
{
containerLayout->addWidget(new MessageReadWidget(*it));
}
QWidget *containerWidget = new QWidget;
containerWidget->setLayout(containerLayout);

myMessagesScroll = new QScrollArea(this);
myMessagesScroll->setWidget(containerWidget); //containerWidget becomes a child of myMessagesScroll
myMessagesScroll->setWidgetResizable(true);

messagesBox = new QGroupBox(title, this);
QVBoxLayout *messagesBoxLayout = new QVBoxLayout;
messagesBoxLayout->addWidget(myMessagesScroll);
messagesBox->setLayout(messagesBoxLayout);

QVBoxLayout *myLayout = new QVBoxLayout;
myLayout->addWidget(messagesBox);
setLayout(myLayout);
}

MessageScrollBox::~MessageScrollBox()
{
qDebug() << "Destroying MessageScrollBox";
}

void MessageScrollBox::refreshMessages()
{
QVBoxLayout *newContainerLayout = new QVBoxLayout;

for (QVector<Message*>::const_iterator it = myMessages->constBegin(); it != myMessages->constEnd(); ++it)
{
newContainerLayout->addWidget(new MessageReadWidget(*it));
}
QWidget *newContainerWidget = new QWidget;
newContainerWidget->setLayout(newContainerLayout);

QWidget *oldContainerWidget = myMessagesScroll->widget();
myMessagesScroll->setWidget(newContainerWidget);
oldContainerWidget->deleteLater();
}

wysota
21st September 2011, 18:44
Because it's quicker?
In terms of lines of code you have to write or in terms of execution time? Certainly not the latter, hard to say about the former.


Inside the QWidget is layout which holds a whole bunch of QWidgets, some of which I need to remove.
Why don't you just remove the widgets you don't want and leave the rest unchanged?

amleto
21st September 2011, 19:14
honestly, it looks poorly designed. You should have some class/functionality that handles the messages and knows how to handle new ones, and what to do when old ones get too old.

Does widgetInABox become a child of messagesBox?
qwidgets in layouts will become children of the widget which owns the layout. (so yes you your question)

The 11th plague of Egypt
21st September 2011, 19:43
Thank you, it may be poorly designed, but I just need it to work.
I'll make it more complex and faster when needed.

BTW the very last line causes a segfault, I don't know why
oldContainerWidget->deleteLater();

wysota
21st September 2011, 19:57
Thank you, it may be poorly designed, but I just need it to work.
I'll make it more complex and faster when needed.
I read your code again. Are you sure you shouldn't be using QListWidget instead of all those widgets of yours?


BTW the very last line causes a segfault, I don't know why
oldContainerWidget->deleteLater();
You are probably dereferencing a null pointer.

The 11th plague of Egypt
21st September 2011, 20:12
I read your code again. Are you sure you shouldn't be using QListWidget instead of all those widgets of yours?
I don't really know, here's how the thing looks (in its horrible appearence).
http://img15.imageshack.us/img15/1782/sshot817.png (http://imageshack.us/photo/my-images/15/sshot817.png/)


I read your code again. Are you sure you shouldn't be using QListWidget instead of all those widgets of yours?
You are probably dereferencing a null pointer.
Right! I just reread the QScrollArea::setWidget documentation, and noticed this...

The widget becomes a child of the scroll area, and will be destroyed when the scroll area is deleted or when a new widget is set.

wysota
21st September 2011, 20:15
I don't really know, here's how the thing looks (in its horrible appearence).
Yes, I'd say you should use QListWidget with a custom delegate :)

The 11th plague of Egypt
21st September 2011, 21:06
Nice idea, makes me curious. The content I display is static (the QLineEdits are set to read only).

I'm thinking about creating empty QListWidgetItems and then using this function to display my custom widgets. Is that ok?
void QListWidget::setItemWidget ( QListWidgetItem * item, QWidget * widget )

Or can I directly create a QListWidgetItem that integrates my widget?
EDIT: In this case, I need to get my widgets destroyed when the list is cleared.

QItemDelegate seems a little more advanced, I'm not sure I can handle it.

The 11th plague of Egypt
28th September 2011, 17:50
Bump

I'm still wondering if and how I can add a QWidget to a QListWidget. Would this work?


QWidget *myWidget = new MessageReadWidget(...);
QListWidget *myQListWidget = new QListWidget(this);
myQListWidget->setItemWidget (new QListWidgetItem(myQListWidget), myWidget);

wysota
28th September 2011, 18:02
It would, but it would get terribly slow and your widget would not be related to the item's contents in any way.

The 11th plague of Egypt
28th September 2011, 18:07
Better or worse than adding them all to a QScrollArea?

Is there a cleaner way to do what I need without getting too complex?

wysota
28th September 2011, 18:18
I think you should just implement your own delegate. If you don't want to, then stick with QScrollArea, there is no point in using QListWidget if you don't want to have any items anyway.

The 11th plague of Egypt
28th September 2011, 18:29
Thank you. I can't really understand what a delegate is, got any quick tutorial/code snippet?

BTW is there a way to know how many tabs a tabwidget has? I need to destroy them all, and clear() is not sufficient.

wysota
28th September 2011, 18:41
Thank you. I can't really understand what a delegate is, got any quick tutorial/code snippet?
You can start with QAbstractItemDelegate docs and then head to Star Delegate example.


BTW is there a way to know how many tabs a tabwidget has? I need to destroy them all, and clear() is not sufficient.
QTabWidget::count()