Laying out items/widgets without stretching/spacing
-
After all these years of using Qt I still find getting what I want in layouts a "dark art". Yes, I have read the docs many times but seeming without clarity/true understanding :) So I thought I would ask about one simple case which I find myself wanting often. [This post inspired by thinking about https://forum.qt.io/post/832780 but not directly related to the issue there.]
I would like, as an example:
- A horizontal layout inside some parent widget.
- I will want to place some widgets (e.g.
QPushButton
s andQLabel
s) on it. - I want all items laid out left to right, taking up their "natural" width, with no stretching/spacing before/between/after them. So the line of them will take up no more width than they need, they will be "packed" from left to right and there will be a gap/nothing to the right of them.
When I Google for examples of this, or ask an AI, I see either (a) add a spacer as an extra, final item on the layout or (b) add a stretch on the final widget.
And this "works" but for me it is not "right". For one thing it requires code which, say, wants to add a new final widget to "know" about the layout and code accordingly: in case (a) it must know not to append the new widget but rather insert it one before the the final spacer while in case (b) the stretch on the current final item must be removed and added to the newly added final item.
What I want or expect is there should be an attribute/property specified once on the whole layout (not on any widget(s)) to say "this runs left to right with no spacing or right-justification", no matter what/when you might add any widgets.
Is there such a simple property available on a layout? Have I missed something really easy which does this?
P.S.
In case anyone says: I have used the Qt "flow layout" example code when I have genuinely wanted multiline flow layout. And that effectively does make each line as I want. But the code for that is way too big/complex for just a single line/horizontal layout where I want widgets laid out left to right with no spacing.@JonB said in Laying out items/widgets without stretching/spacing:
Is there such a simple property available on a layout? Have I missed something really easy which does this?
I don't think there is something like this. Adding a spacer to the right is how it is normally done. You could derive from QHBoxLayout and automatically add the spacer to the right/insert widgets before the space by just overloading
addWidget()
. -
@JonB said in Laying out items/widgets without stretching/spacing:
Is there such a simple property available on a layout? Have I missed something really easy which does this?
I don't think there is something like this. Adding a spacer to the right is how it is normally done. You could derive from QHBoxLayout and automatically add the spacer to the right/insert widgets before the space by just overloading
addWidget()
.@SimonSchroeder
Thank you, for what appears to be confirmation of my understanding. I just don't get it.A horizontal layout (and of course all this applies to vertical layouts too, and perhaps other layouts) starts life as a container which apparently chooses to spread its content evenly across its width (right?). Then it seems "obvious" and "natural" to me that should be some "attribute" on the layout which one could alter to, say, "lay out from left with no extra spacing" and "lay out from right with no extra spacing", corresponding to "left align" and "right align", and perhaps another one of "center in layout, with no extra spacing" for "center align".
I have used other UI toolkit designers and they worked like that, e.g. I'm pretty sure when I did Windows/Visual Studio it offered this basic functionality without having to do "stretch" or "spacer". This seems so basically obvious to me as a facility one would offer.
Ah well. I shall do a bit more Googling and then presumably close this thread, with regret.
-
After all these years of using Qt I still find getting what I want in layouts a "dark art". Yes, I have read the docs many times but seeming without clarity/true understanding :) So I thought I would ask about one simple case which I find myself wanting often. [This post inspired by thinking about https://forum.qt.io/post/832780 but not directly related to the issue there.]
I would like, as an example:
- A horizontal layout inside some parent widget.
- I will want to place some widgets (e.g.
QPushButton
s andQLabel
s) on it. - I want all items laid out left to right, taking up their "natural" width, with no stretching/spacing before/between/after them. So the line of them will take up no more width than they need, they will be "packed" from left to right and there will be a gap/nothing to the right of them.
When I Google for examples of this, or ask an AI, I see either (a) add a spacer as an extra, final item on the layout or (b) add a stretch on the final widget.
And this "works" but for me it is not "right". For one thing it requires code which, say, wants to add a new final widget to "know" about the layout and code accordingly: in case (a) it must know not to append the new widget but rather insert it one before the the final spacer while in case (b) the stretch on the current final item must be removed and added to the newly added final item.
What I want or expect is there should be an attribute/property specified once on the whole layout (not on any widget(s)) to say "this runs left to right with no spacing or right-justification", no matter what/when you might add any widgets.
Is there such a simple property available on a layout? Have I missed something really easy which does this?
P.S.
In case anyone says: I have used the Qt "flow layout" example code when I have genuinely wanted multiline flow layout. And that effectively does make each line as I want. But the code for that is way too big/complex for just a single line/horizontal layout where I want widgets laid out left to right with no spacing.@JonB have you heard of the Flow Layout example?
https://doc.qt.io/qt-6/qtwidgets-layouts-flowlayout-example.html
I think it does exactly what you're looking for
-
@JonB have you heard of the Flow Layout example?
https://doc.qt.io/qt-6/qtwidgets-layouts-flowlayout-example.html
I think it does exactly what you're looking for
@J.Hilk
If you read my question I carefully put in:P.S.
In case anyone says: I have used the Qt "flow layout" example code when I have genuinely wanted multiline flow layout. And that effectively does make each line as I want. But the code for that is way too big/complex for just a single line/horizontal layout where I want widgets laid out left to right with no spacing.
:)
Yes, I have used flow layout where i wanted multiline flow layout. I even (had to) fix at least one "bug" in it. So I know it well. And as I said it is a lot of code, and (as I recall) uses absolute positioning to achieve it (that may not be correct, but it has to do a lot of measuring in order to calculate what should be pushed to the next line at least). Qt layout must already be doing a lot of work to achieve the "spread evenly across", I simply want it to offer not to do that and just lay out in the simplest way from left to right, and perhaps from right to left too.
For the record, these layout features are certainly available in a very simple and default fashion from Visual Studio. No need for "spacers" or "stretchers".
-
@J.Hilk
If you read my question I carefully put in:P.S.
In case anyone says: I have used the Qt "flow layout" example code when I have genuinely wanted multiline flow layout. And that effectively does make each line as I want. But the code for that is way too big/complex for just a single line/horizontal layout where I want widgets laid out left to right with no spacing.
:)
Yes, I have used flow layout where i wanted multiline flow layout. I even (had to) fix at least one "bug" in it. So I know it well. And as I said it is a lot of code, and (as I recall) uses absolute positioning to achieve it (that may not be correct, but it has to do a lot of measuring in order to calculate what should be pushed to the next line at least). Qt layout must already be doing a lot of work to achieve the "spread evenly across", I simply want it to offer not to do that and just lay out in the simplest way from left to right, and perhaps from right to left too.
For the record, these layout features are certainly available in a very simple and default fashion from Visual Studio. No need for "spacers" or "stretchers".
-
@JonB may bad
I think if you provide max or fixed sizes, normal layouts work that way?
I'm not entirely sure, been ages since I last used QWidgets
@J.Hilk said in Laying out items/widgets without stretching/spacing:
I think if you provide max or fixed sizes, normal layouts work that way?
I don't think so (but I will play with it again shortly). Not that I should have to or want either max or fixed sizes on widgets. When you do nothing special on the widgets a horizontal layout spreads them evenly across with "gaps" between each to achieve full justification from left to right, without changing the width of each one. I just want it not to do the "spread out" work and just place them left to right with no extra work. Simplez ;-)
-
Most of the time I am just using a grid layout. This will help align widgets over multiple rows. The remaining cases where I do use QHBoxLayout I really want to spread it over the full width (or in the opposite direction: I want the dialog as narrow as possible so that there is no space for a spacer left). This leaves very few cases for spacer items in my layouts. Sometimes there is also some input element that can profit from more space and I'll make that one stretch (and thus don't need no additional spacer).
-
After all these years of using Qt I still find getting what I want in layouts a "dark art". Yes, I have read the docs many times but seeming without clarity/true understanding :) So I thought I would ask about one simple case which I find myself wanting often. [This post inspired by thinking about https://forum.qt.io/post/832780 but not directly related to the issue there.]
I would like, as an example:
- A horizontal layout inside some parent widget.
- I will want to place some widgets (e.g.
QPushButton
s andQLabel
s) on it. - I want all items laid out left to right, taking up their "natural" width, with no stretching/spacing before/between/after them. So the line of them will take up no more width than they need, they will be "packed" from left to right and there will be a gap/nothing to the right of them.
When I Google for examples of this, or ask an AI, I see either (a) add a spacer as an extra, final item on the layout or (b) add a stretch on the final widget.
And this "works" but for me it is not "right". For one thing it requires code which, say, wants to add a new final widget to "know" about the layout and code accordingly: in case (a) it must know not to append the new widget but rather insert it one before the the final spacer while in case (b) the stretch on the current final item must be removed and added to the newly added final item.
What I want or expect is there should be an attribute/property specified once on the whole layout (not on any widget(s)) to say "this runs left to right with no spacing or right-justification", no matter what/when you might add any widgets.
Is there such a simple property available on a layout? Have I missed something really easy which does this?
P.S.
In case anyone says: I have used the Qt "flow layout" example code when I have genuinely wanted multiline flow layout. And that effectively does make each line as I want. But the code for that is way too big/complex for just a single line/horizontal layout where I want widgets laid out left to right with no spacing.@JonB said in Laying out items/widgets without stretching/spacing:
I would like, as an example:
- A horizontal layout inside some parent widget.
- I will want to place some widgets (e.g. QPushButtons and QLabels) on it.
- I want all items laid out left to right, taking up their "natural" width, with no stretching/spacing before/between/after them. So the line of them will take up no more width than they need, they will be "packed" from left to right and there will be a gap/nothing to the right of them.
It is actually possible. Just using a QHBoxLayout and call
setAlignment(Qt::AlignLeft)
on it, also all the widgets in it should not be set to be stretching/expanding.From https://doc.qt.io/qt-6/qlayoutitem.html#setAlignment:
Note: Item alignment is only supported by QLayoutItem subclasses where it would have a visual effect. Except for QSpacerItem, which provides blank space for layouts, all public Qt classes that inherit QLayoutItem support item alignment.
And from https://doc.qt.io/qt-6/qboxlayout.html#addWidget (this explains alignment's effect):
The default alignment is 0, which means that the widget fills the entire cell.
This should work in QBoxLayout and QGridLayout. But there's one QLayout subclass I've found that item alignment doesn't work in it, is QStackedLayout.
-
@JonB said in Laying out items/widgets without stretching/spacing:
I would like, as an example:
- A horizontal layout inside some parent widget.
- I will want to place some widgets (e.g. QPushButtons and QLabels) on it.
- I want all items laid out left to right, taking up their "natural" width, with no stretching/spacing before/between/after them. So the line of them will take up no more width than they need, they will be "packed" from left to right and there will be a gap/nothing to the right of them.
It is actually possible. Just using a QHBoxLayout and call
setAlignment(Qt::AlignLeft)
on it, also all the widgets in it should not be set to be stretching/expanding.From https://doc.qt.io/qt-6/qlayoutitem.html#setAlignment:
Note: Item alignment is only supported by QLayoutItem subclasses where it would have a visual effect. Except for QSpacerItem, which provides blank space for layouts, all public Qt classes that inherit QLayoutItem support item alignment.
And from https://doc.qt.io/qt-6/qboxlayout.html#addWidget (this explains alignment's effect):
The default alignment is 0, which means that the widget fills the entire cell.
This should work in QBoxLayout and QGridLayout. But there's one QLayout subclass I've found that item alignment doesn't work in it, is QStackedLayout.
@Bonnie said in Laying out items/widgets without stretching/spacing:
Just using a QHBoxLayout and call setAlignment(Qt::AlignLeft) on it
Hey, that might be 100% just what I was looking for! I looked for some sort of "alignment" but couldn't spot it, maybe because it's on some subclass, even though I thought I checked there. This sounds much more reasonable, will try it soon and report back....
-
@JonB said in Laying out items/widgets without stretching/spacing:
I would like, as an example:
- A horizontal layout inside some parent widget.
- I will want to place some widgets (e.g. QPushButtons and QLabels) on it.
- I want all items laid out left to right, taking up their "natural" width, with no stretching/spacing before/between/after them. So the line of them will take up no more width than they need, they will be "packed" from left to right and there will be a gap/nothing to the right of them.
It is actually possible. Just using a QHBoxLayout and call
setAlignment(Qt::AlignLeft)
on it, also all the widgets in it should not be set to be stretching/expanding.From https://doc.qt.io/qt-6/qlayoutitem.html#setAlignment:
Note: Item alignment is only supported by QLayoutItem subclasses where it would have a visual effect. Except for QSpacerItem, which provides blank space for layouts, all public Qt classes that inherit QLayoutItem support item alignment.
And from https://doc.qt.io/qt-6/qboxlayout.html#addWidget (this explains alignment's effect):
The default alignment is 0, which means that the widget fills the entire cell.
This should work in QBoxLayout and QGridLayout. But there's one QLayout subclass I've found that item alignment doesn't work in it, is QStackedLayout.
@Bonnie
I have now had a chance to play with this.hlayout->setAlignment(Qt::AlignLeft)
was 100% what I had in mind (and e.g.AlignRight
orAlignHCenter
)! Thank you, I just could not find it. Marking your post as the correct answer.I really don't know why other people/Googling/ChatGPT don't seem to mention this, and all claim you need to do it with "spacers" or "stretchers". Those are cumbersome when
QLayoutItem::setAlignment()
is simpler and better at the job.... -
J JonB has marked this topic as solved