4

I've had a real challenge getting QScrollArea to take the minimum space possible up to a maximum height.

My GUI model is as follows: A QScrollArea contains a vertical layout which is populated with a widget of class TableRow. I want this class TableRow to take up the minimum height possible. It has a widget at the top which is always visible, and a QScrollArea below which has a label inside it whose visibility can be toggled. The label is for notes which may be 0 characters or may be infinite in length (hardware limitations aside).

I've found that for a label in class TableRow setting the vertical sizePolicy to Fixed will actually take up exactly how much it needs to fit all the contents (see: Qt Layout, resize to minimum after widget size changes). However this doesn't appear to work with QScrollArea. In fact every sizePolicy I've tried keeps the QScrollArea at a fixed height; except for Ignore, but then the QScrollArea goes to a height of 0, regardless of its contents.

I've created a git branch producing a simplified version of this problem.

Here is the result of applying a fixed vertical sizePolicy: Result of fixed vertical sizePolicy

What I'm expecting from this test case:

  • The first widget's height should be almost 30px (the height of the upper widget) only showing the borders for the QLabel and QScrollArea
  • The second widget's height should be shorter than 130px (the maximum height of the QScrollArea being 100px) but large enough to show the label without scrolling
  • The third widget's height should be 130px, and the scrollbar should appear (this part is correct in every case I've tried except for when the vertical sizePolicy is set to Ignored )

I understand I may need to override some things to make this work, as by itself it's not obvious why a QScrollArea's height might be dependent on its child widgets (which is probably why it was not designed to make this easy, or at least it seems like it wasn't).

However, I think the case I'm trying to make is common enough, and my current approach is justifiable. If there's another/better way to make an individual widget scroll after it reaches a maximum height I'm open to that as an answer, provided it meets the three conditions I'm expecting.

Assimilater
  • 944
  • 14
  • 33
  • Have you tried setting size policies on the viewports instead of the scroll areas themselves? – jonspaceharper May 16 '15 at 21:42
  • Probably not. What's a viewport? :) – Assimilater May 16 '15 at 22:00
  • Google: The viewport is the widget inside the QScrollArea in which all child widgets are rendered? I have also tried adjusting this, yes. Currently I have it set for `Fixed` – Assimilater May 16 '15 at 22:07
  • If the viewport is a fixed size, it won't dynamically adjust the way you need it to. Try working with the layouts' `sizeConstraint` properties and the stretch, perhaps? – jonspaceharper May 18 '15 at 21:28
  • Do you have a suggested combination of sizeHint/sizeConstraint/stretch on the viewport/layout? My attempted combinations have been to no avail. I believe I need the viewport to be a fixed size though. As I learned from the SO Link I posted, fixed will actually assume the minimum space required. This appears to hold true for the viewport as well, from what I've been able to test. Also, forcing it smaller with a maximum size has no effect on the ScrollArea. Though I could be misinterpreting what I see when I debug. – Assimilater May 19 '15 at 16:36

1 Answers1

3

This feels more like a hack than a solution, but it does work for me, at least in the short term. Because the text for lblNotes does not change runtime, I was able to add the following code in the constructor of my TableRow widget:

// Hack to resize QScrollAreas
ui->lblNotes->adjustSize(); // Otherwise lblNotes will think its height is still ~0px
int height = ui->lblNotes->height() + 12; // Borders and margins add up to 12px
if (height > 100) { height = 100; } // Cap the height at desired maximum value
ui->scrollArea->setFixedHeight(height);

Should I have to deal with the case of dynamically set text, I could wrap this in a function to be called anytime the text of lblNotes is set.

I'm still open to solutions that involve using the layout features Qt has natively as I believe that would be preferred if a solution exists. Some QScrollArea contents may not be as straight-forward to determine the height from in the future.

Assimilater
  • 944
  • 14
  • 33