How to do a "no break" QHBoxLayout
-
I have an up-coming requirement which I haven't had a chance to play with yet but anticipate an issue I'd like to clarify in advance.
There are to be a whole load of widgets in horizontal flow which must "wrap" (not scroll right) to the next line down when they reach the window width, which will vary on different devices. I do not want to force where the move-down occurs, it should only do it when it reaches the width:
XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
I presume this is no problem, the containing
QHBoxLayout
will expand vertically to wrap at the right point (correct?).(Having said that: which "expanding flag" will it need to ensure it wraps when it reaches a width rather than keep on going right, given that I don't have an explicit maximum width? Will I have to look at the desktop width and apply that value as a maximum?)
Now, my real question is: at the end of the the
XXX
widgets I have a few differentYYY
widgets. I want those horizontal, after a gap, but I do not want these to ever be broken onto a line below such that they get split:XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX YYY YYY YYY
The above is good, because the
YYY
s are all together horizontally.XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX YYY YYY YYY
The above is bad, because the
YYY
s are split. It would need to be:XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX YYY YYY YYY
Hence it's like a "no-break"/"keep-together" in a word processor or whatever on the
YYY
s.How will I achieve that? I imagine I'll want the
YYY
s in their ownQHBoxLayout
on the overallQHBoxLayout
, but how will I indicate this sub-QHBoxLayout
must not be split/broken and must wrap to the next line as a whole if there is not enough horizontal room for it on its parentQHBoxLayout
? -
Hi,
I think you'll be interested in the Flow Layout Example for the layouting you seek.
-
@SGaist
I have looked at that, and now looked at theQBoxLayout
methods & docs. Now I don't know whether it implements what I assumed & need:Docs:
QBoxLayout takes the space it gets (from its parent layout or from the parentWidget()), divides it up into a row of boxes, and makes each managed widget fill one box.
Your example:
The position of each item in the layout is then calculated by adding the items width and the line height to the initial x and y coordinates. This in turn lets us find out whether the next item will fit on the current line or if it must be moved down to the next.
I assumed it handled a horizontal flow where the items exceeded its width and it could auto-wrap to the "next line" down if they exceeded. Like an HTML
DIV
element does:<div width="1000px"> XXX XXX XXX XXX XXX XXX XXX XXX </div>
would give
XXX XXX XXX XXX XXX XXX XXX XXX
but
<div width="100px"> XXX XXX XXX XXX XXX XXX XXX XXX </div>
would give
XXX XXX XXX XXX XXX XXX XXX XXX
So it just flows elements as necessary. But the docs only shows a
QHBoxLayout
placing all its contents on one "line". I don't expect to have to use a grid and calculate it myself.That is the first part of my question. Does a
QHBoxLayout
allow stuff to flow below (like "word wrap") or not, please? If not, is there a different layout/widget which behaves like a simpleDIV
, I would have thought this was an extremely common requirement for layout? -
No it's not. The desktop application world and the web world are radically different. Qt widgets predates the single page web concept.
As for QHBoxLayout, no, it won't automatically do wrapping as its goal is to handle horizontality hence my example suggestion.
-
@SGaist
Got it! Then I was certainly labouring under a misapprehension. I do understand about desktop vs web, though by Qt standards I am "surprised" there isn't a wrap-flow-layout. I now understand why you referred to me to example which has to calculate. I'll do a little Googling to see if others have asked about this, and refer to your sample code when I discover I have no alternative than to do it manually :) ... That didn't take long, same kind of questions on SO point to same flow layout example! Thanks for enlightening me. -
@SGaist , or @ whoever
I need some help, please, with making the supplied Qt Flow Layout Example work correctly which I have been referred to, and so have re-opened this thread.I have translated it to Python/PyQt successfully, that is not the issue.
The supplied example
main.cpp
adds only widgets to the layout, viaQLayout::addWidget()
. As per https://doc.qt.io/qt-5/qlayout.html#addWidget, that in turn calls theFlowLayout::addItem(QLayoutItem *item)
override, with aQWidgetItem
foritem
, which adds it to its internalQList<QLayoutItem *> itemList
used in calculating. All this works fine.I need to add little layouts (as it happens,
QVBoxLayout
, though I'd like it to work if I ever addQHBoxLayout
s) to theFlowLayout
. The baseQLayout
does not haveaddLayout()
in the way it hasaddWidget()
. Purely at a guess, I have made my code go:layout = QVBoxLayout() ... flowLayout.addChildLayout(layout) flowLayout.addItem(layout)
This seems to work. I seem to need the
addItem()
to put it inFlowLayout::itemList
. I thought I also neededaddChildLayout()
to actually add the layout onto theFlowLayout
, but I can get rid of that line and it still seems to work/look the same.So... what is the correct/required way to add a
QLayout
rather than aQWidget
onto theFlowLayout
? Do I just need to callFlowLayout::addItem()
and that's it? I don't really get how that is working:void FlowLayout::addItem(QLayoutItem *item) { itemList.append(item); }
Since all that does it appends to its internal list for calculating, I don't see how that is actually adding my sub-layout onto the
FlowLayout
...?Yours, :confused:
-
Hello!
How about using
QGridLayout
instead ofQHBoxLayout
, you can set therow
,column
andalignment
of yourwidgets
: https://doc.qt.io/qt-5/qgridlayout.html#addWidget-1Also it should expand to your needs by setting
setSizePolicy
to yourwidgets
: https://doc.qt.io/qt-5/qwidget.html#setSizePolicy-1 -
@Cobra91151
A grid layout doesn't do what a flow layout does. It won't flow things from line to line which is the whole point. -
@JonB said in How to do a "no break" QHBoxLayout:
what is the correct/required way to add a QLayout rather than a QWidget onto the FlowLayout
Can't you add a widget which in turn has a layout in it?
-
@jsulm
Firstly, this newFlowLayout
is to be a slot-in replacement for existingQHBoxLayout
s which useaddLayout()
in generic functions to add stuff onto them. Doing it by adding in a new widget may be an issue.Secondly, https://doc.qt.io/qt-5/layout.html states:
You can nest layouts using
addLayout()
on a layout; the inner layout then becomes a child of the layout it is inserted into.QBoxLayout
, which derives fromQLayout
, has anaddlayout()
, butQLayout
itself does not. There isQLayout::addItem()
, which is what I am overriding/asking about. It takes aQLayoutItem
, which includes aQLayout
object, not just aQWidgetItem
one, so I'm trying figure how to do that correctly.If the answer is "I've looked at that Qt sample, and
FlowLayout
is only to be used to add widgets, not layouts", I will respect that. But since adding a sub-layout seems to be working, though I don't get how, I thought it would be easiest if I pursued that direction? -
Nothing wrong with adding a layout. See the implementation of QBoxLayout::insertLayout.