PDA

View Full Version : Nesting QScrollAreas



Computer Hater
3rd August 2011, 14:42
Hi,

I'm trying to build a scrollable list of data lines with several data fields each, and a headline describing those data fields.
Of course, I don't want the headline to be scrolled out of focus when scrolling down. However, since the lines hold quite a few items, I want the headline to be included in any horizontal scrolling event and synchronized with the actual data fields, to make the most use of the horizontally available space.

Something like this:

Item name -- Data field 1 -- Data field 2 -- Data field 3 -- ...
Item1 Value11 Value12 Value13 ...
Item2 Value21 Value22 Value23 ...
Item3 Value31 Value32 Value33 ...
...

To do this, I have tried nesting two QScrollAreas. But I always get the problem that with two nested QScrollAreas the total size of the area is fixed and doesn't make use of more space available (see screenshot), while a single QScrollArea always does.

The test code is a bit improvised and combines a scroll area in Designer with another one that is directly coded.
I had the same problem when all elements were hand-coded.



MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

codedScrollArea = new QScrollArea;
codedSAWidget = new QWidget;
codedSALayout = new QHBoxLayout;
uiSALayout= new QHBoxLayout;

label = new QLabel*[15];
QString labeltext;
for (int l = 0; l < 15; l++)
{
labeltext = "Label ";
labeltext += QString::number(l);
label[l] = new QLabel(labeltext);
codedSALayout->addWidget(label[l]);
}
codedSAWidget->setLayout(codedSALayout);
codedScrollArea->setWidget(codedSAWidget);
uiSALayout->addWidget(codedScrollArea);

ui->scrollAreaWidget->setLayout(uiSALayout);
}


Can anyone give me a hint how to make two nested QScrollAreas use the available space, or how to otherwise implement such a list with a headline ?
Thank you !

Lykurg
3rd August 2011, 14:55
Ehm, I can't see that you have set a layout to your main window. And can't you use QTableView or QTableWidget? Or QList* or QTree*?

Computer Hater
3rd August 2011, 21:59
You're right. I forgot to install a layout on the main window. After I did so, the QScrollArea resized properly.
However, the problem persists in my main application, where I try the same thing, except that it's supposed to be one of several tabs in a QTabWidget.
I thought I had reconstructed the problem in the sample, when it was in fact apparently a different problem.



Tab2::Tab2(QWidget *parent) : QWidget(parent)
{
sArea1 = new QScrollArea;
sArea2 = new QScrollArea;
sa1Layout = new QHBoxLayout;
sa2Layout = new QHBoxLayout;
mainLayout = new QHBoxLayout;
sa1Widget = new QWidget;
sa2Widget = new QWidget;

QString labeltext;
label = new QLabel*[20];
for (int l = 0; l < 20; l++)
{
labeltext = "Label";
labeltext += QString::number(l);
label[l] = new QLabel(labeltext);
sa1Layout->addWidget(label[l]);
}
sa1Widget->setLayout(sa1Layout);
sArea1->setWidget(sa1Widget);
sa2Layout->addWidget(sArea1);
sa2Widget->setLayout(sa2Layout);
sArea2->setWidget(sa2Widget);

mainLayout->addWidget(sArea2);
this->setLayout(mainLayout);
}


I would like to understand why the problem occurs in this context. I will check out the other classes as alternatives though.

Lykurg
3rd August 2011, 22:28
The documentation is your friend. I guess you should have a look at QScrollArea::setWidgetResizable().

Computer Hater
3rd August 2011, 22:58
Thank you !
Using that function, the inner QScrollArea now resizes itself to utilize the space.

Although I'm almost too shy to ask:
- Why do I need to set the resizable property of the outer QScrollArea (sArea2) so that the inner one (sArea1) resizes properly ?
- Why does the test line of labels move from the top to the vertical middle of the screen in the already resized inner QScrollArea when I set sArea1's resizable property as well ?

It's going to take a while until I really understand all the interactions in Qt.
Anyway, thank you again ! You saved my day ! (Really !)

Lykurg
4th August 2011, 08:09
1) the scroll area has no layout management thus the added widget has its original (QWidget::sizeHint) size regardless of the geometry of the scroll area. (That is what you normally want. Think of an image browser. You want to be able to scale the image down even if it is smaller than the area size.) With the resizable property you turn on a "layout" for the area.

2) The added widget itself has a layout. So you have to adjust that to take care that that widget gets the free space you want. In your case try to give the inner scroll area an expanding size hint.

Computer Hater
4th August 2011, 11:03
Thank you again for your explanations, Likurg.
But I think there was a misunderstanding.

My question #1 referred to the situation that when I specifically set the 'widgetResizable()' property, I only got the actual resizing effect for the interior QScrollArea 'sArea1' upon setting the resizable flag for the exterior QScrollArea 'sArea2', which I can't make sense of.
Whereas your answer seems to have explained the interdependence between a single QScrollArea and its widget.

Consequently, there may have been a misunderstanding in question 2 as well.
What I meant was that upon setting (only) the exterior QScrollArea 'sArea2's resizable flag, the sample line of labels insides 'sArea1' was situated at the very top. Then, when I set 'sArea1's resizable flag as well, that line instead was pulled down and centered in its vertical alignment, despite the same space being available in both cases. I wondered how setting the resizable flag would cause a vertical middle justification of that line.

Also, in your answer to question #2, did you mean expanding size policy instead of size hint ? The documentation says 'size hint' is a QSize, which doesn't appear to have an expanding attribute.

I'm sorry if I happen to make the issue more complicated than it needs to be by adding even more questions, perhaps even misunderstanding your answers.

--
On another note, I think I've also figured out why the resizing instantly worked in the partially Qt Designer-made example (after applying the main layout) without specifically setting 'widgetResizable()', but not in the fully coded version:
Qt Designer seems to automatically create QScrollAreas with that flag enabled, whereas the coded default version has it disabled.