QScrollArea with list of custom widgets
-
Hello everyone,
I'm having trouble building a scrollable list of custom widgets.
After spending a few days trying I now know that I dont know enough about the Qt Layout system to make this work.To give a better understanding of what I am looking for, I created a small picture:
(Follow the Link if it is not displayed correctly)
Okay. Everything in the picture is the contents of my QScrollArea.
In the ScrollArea I created a QWidget for containing everything.
The inner custom widgets are Chat-Bubbles, like in WhatsApp or other App-Style messengers. As they contain text and some additional information, it is not possible to give a definitive size-hint.Questions:
- How can the described behavior be achieved? Everything I have found and/or tried said that I should set size hints, which does not really work with heightForWidth, at least in my case.
- Do I have to create a custom Layout Manager for this?
If there are any questions I will try to help.
Thank you in advance!
-
Hi,
Since it's for a chat like thingy, did you consider using e.g. QListView with a custom QStyledItemDelegate ?
-
I have used a scroll area for something similar. I setup mine a little different. I use widgets to contain each child item (not layouts)
// constructor of parent widget scroll_area = new QScrollArea(this); scroll_area->setWidgetResizable(true); parent_widget_layout->addWidget(scroll_area); d_scroll_area_widget = new QWidget(); scroll_area->setWidget(d_scroll_area_widget); d_scroll_area_layout = new QVBoxLayout(d_scroll_area_widget); // see note below for explanation of spacer d_bottom_vertical_spacer = new QSpacerItem(100, 20, QSizePolicy::Minimum, QSizePolicy::Expanding); d_scroll_area_layout->addItem(d_bottom_vertical_spacer);
Too add items
d_scroll_area_layout->removeItem(d_bottom_vertical_spacer); ... d_scroll_area_layout->addWidget(new_widget_item); d_scroll_area_layout->addItem(d_bottom_vertical_spacer);
The bottom spacer is to make sure that if there is only one child widget of the scroll area it is not resized to fill all the available space. The bottom spacer is always moved to the bottom.
Removing items is a bit more tougher. Actually, in my implementation, I don't. I hide the ones I want to remove and re-assign them if they are re-used in the future. In my case it works for what I need it to do but it may not be practical if you have something where you want to insert / delete / move items.
As @SGaist mentioned you can use a QListView/QListWidget. The items do not need to be the same size and they can be resized after the fact if more or less information is displayed which changes the size.
// Constructor d_ReportListView = new TListView; // subclass of QListWidget d_ReportListView->setDragEnabled(true); d_ReportListView->setDragDropMode(QAbstractItemView::InternalMove); d_ReportListView->setSelectionMode(QAbstractItemView::ExtendedSelection); d_ReportListView->setAutoScroll(true); d_ReportListView->setAutoScrollMargin(48); d_ReportListView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); d_ReportListView->setUniformItemSizes(false); d_ReportListView->setResizeMode(QListView::Adjust); // important function to enable resizing QListWidgetItems // if a list widget item size is changed update the size hits of that item void TListView::UpdateSizeHints(void) { TListViewItem *LVItem; QSize ItemSize; int LineHeight; LineHeight = TListViewItem::LineHeight(); // fixed line height ItemSize = this->size(); // size of parent ItemSize.setHeight(num_lines * LineHeight); // only adjusting height to fit required lines // LVItem = pointer to current QListWidgetItem that need to be set or changed LVItem->setSizeHint(ItemSize); }