Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct
Too many widgets breaks window management
Eric Singer last edited by Eric Singer
I'm building a Windows desktop application in 5.14.1. I have QFrames inside a vertically-resizable QSplitter. Each QFrame has a varying number of QWidgets added dynamically as rows in the QFrames. The rows are rectangular line graphs that span their QFrame horizontally. (Images attached.)
If I add too many rows, they force the QFrame to grow past any vertical limit I set, regardless of size policy, expanding the application window below the bottom of the display. If I turn on the vertical scroll bar, no problem - the scroll bar appears, the frame won't over-grow, and it can be scrolled to see the lower rows.
However, in this application, my frames can not have vertical scroll bars. Widgets should display to the bottom of the QFrame, and any that don't fit should get cut off or not display. (The user will be notified that there are too many rows to display.)
If they are added to the top QFrame of the QSplitter, it will force the bottom one completely below the screen.
Furthermore, this screws up the main application window's resizability. If I click on the top edge of the app window to vertically resize it, it immediately drops the whole window down about 200 pixels. If I do this repeatedly, the app window will disappear irretrievably below the bottom of the screen.
I have tried many different size policies on various parts (frames, etc.) of the window, but nothing prevents the frames and app window from growing past maximum boundaries. This leads me to believe that both problems (overgrowing frames and resize-jumping) are bugs in the Qt window management system.
Any help and ideas would be very appreciated.
What about using a QScrollArea ?
Eric Singer last edited by
@SGaist As per above, I can't use scrolling in this situation. Using a scroll area but turning off the scrollbars does not help either.
I wouldn't consider that a bug. Built-in layouts are just meant to prioritize proper widgets arrangement within the parent over not resizing the parent.
I see two ways to do this, both being pretty much the same thing but different implementation:
- Get rid of the layout and resize the widgets manually in parent's resize event. They will be automatically cut of by the parent if they don't fit.
- Implement a custom layout - basically same as QVboxLayout but one that allows overflowing and never grows the minimum size hint beyond the parent's size. You could probably try that out by just subclassing QVBoxLayout and re-implementing
@Eric-Singer I was more thinking about hiding the scroll bars rather that disabling them. The widget set on can thus grow as you want without the scroll area getting bigger.
Eric Singer last edited by
@Chris-Kawa Thanks. But why minimumSize()? I would have expected to need to limit maximumSize().
@Eric-Singer Because my suggestion is not to limit the size of the parent but rather to limit what the layout reports as the minimum size required.
minimumSize()returns the minimum amount of space the widget needs to provide so that the layout can fit all the widgets inside it.
maximumSize()is the size beyond which the layout can't reasonable grow the widgets inside.
Maximum size is not useful for this case. Your problem is that the parent widget grows too much and it grows because the minimum size of the layout grows i.e. the minimum amount of space required to lay out the widgets inside grows.
If you return a fake limit, one that is smaller than the sum of all the widgets inside, the parent will be able to keep its size despite all the children in the layout not fitting (visually they will be cropped). You could, for example, return the minimum of the base implementation's value that calculates it based on the content size and some constant value of yours, beyond which you don't want to grow.
To be honest that's pretty much what a scroll area does and I think the suggestion given by @SGaist is a better one as it already does that work for you.