Stretch prevent widgets from being centered
-
I have a vertical layout with the nested horizontal one in the bottom. Everything's ok until I add stretches to the latter one to keep the label and the button closer - they prevent the other widgets from being centered. What's the cause of this behavior?
-
@Kenticent
Do you mean you added just one stretch between... account?
label andSign Up
link? No other stretches? -
@JonB Yes. I didn't find a way to combine the writings while making only one of them clickable, so I separated them into QLabel and QPushButton. The purpose of the stretches is to bring them closer. There are only 2 of them at the bottom - no more others. Here's the code. I think you can guess which widget name corresponds to which GUI element.
QVBoxLayout *verLayout = new QVBoxLayout; QHBoxLayout *horLayout = new QHBoxLayout; horLayout->setContentsMargins(0, 0, 0, 0); horLayout->setSpacing(0); // horLayout->addStretch(); horLayout->addWidget(lbl_); horLayout->addWidget(btn1_); // horLayout->addStretch(); verLayout->setContentsMargins(0, 0, 0, 0); verLayout->setSpacing(40); verLayout->setAlignment(Qt::AlignCenter); verLayout->addWidget(lbl); verLayout->addWidget(usernameLe_); verLayout->addWidget(passwordLe_); verLayout->addWidget(chk_); verLayout->addWidget(btn_); verLayout->addLayout(horLayout); setLayout(verLayout);
-
@Kenticent
Oh I see, you are adding 2 stretches, one before the label and one after the link.Then the problem is those stretches will take up the maximum amount of room. And that will make the horizontal they are in occupy as much room as possible, which will be the whole width; hence the horizontals above it now get pushed to the left. That is the reason for what you see.
horLayout->setSpacing(0);
I am a little surprised this does not produce the minimal distance you want. I don't know why putting in a stretch either side actually makes the spacing any smaller than the
0
you specified. An expert may comment.I never understand/know about Qt's layout spacing/stretching/sizing etc. rules, I just play till I get what I want! Certainly just having those stretches at beginning & end will cause the horizontal layout to be too wide. Does
horLayout->setSizeConstraint(QLayout::SetMinimumSize)
(or maybeQLayout::SetFixedSize
--- actually, despite its name, I think this might be just what you want) help? Why not go into Qt Designer and play there with your layouts till they are right, then just take the required generated code and put it into your explicit code, that's the sort of thing I do. -
A hboxlayout with spacer left and right of the inner widget and it should stay centered
-
@Kenticent
Ah, so I think @Christian-Ehrlicher is sayinghorLayout->addSpacing(0)
(is that right?addSpacing()
with0
, or a big number?) where you currently have the twohorLayout->addStretch()
s? I guess stretches expand the layout container, which you don't want, but spacers reside inside the natural size of the layout. -
@JonB said in Stretch prevent widgets from being centered:
(is that right? addSpacing() with 0, or a big number?)
Neither -> QSpacerItem
-
@Christian-Ehrlicher
I thoughtaddSpacing()
creates aQSpacerItem
? And the docs say:Normally, you don't need to use this class directly. Qt's built-in layout managers provide the following functions for manipulating empty space in layouts:
Class Functions
QHBoxLayout addSpacing(), addStretch(), insertSpacing(), insertStretch()
Anyway, if
QSpacerItem
QSpacerItem::QSpacerItem(int w, int h, QSizePolicy::Policy hPolicy = QSizePolicy::Minimum, QSizePolicy::Policy vPolicy = QSizePolicy::Minimum)
requires a width (and height), so the question is: is that width 0 or large?
-
-
@Christian-Ehrlicher
Got it! Looks likeaddSpacing(0)
doesQSizePolicy::Fixed
or similar, and you wantQSizePolicy::Expanding
, hence you want to create aQSpacerItem
yourself, right? -
@JonB said in Stretch prevent widgets from being centered:
ence you want to create a QSpacerItem yourself, right?
I never work with spacings so I can't say - adding a QSpacerItem is imo easier to understand.
-
@Christian-Ehrlicher
:) I quoted from the doc page forQSpacerItem
:Normally, you don't need to use this class directly. Qt's built-in layout managers provide the following functions for manipulating empty space in layouts:
Maybe you are not "normal" ;-)
-
@JonB @Christian-Ehrlicher Thank you for participating in discussion! I figured out, that despite the ctor of QSpacerItem having Minimum size policy as default parameter, addSpacing() sets one side to Fixed depending on the orientation of the Layout. For the horizontal one it goes as follows.
QLayoutPrivate::createSpacerItem(this, size, 0, QSizePolicy::Fixed, QSizePolicy::Minimum)
Full source code https://code.woboq.org/qt5/qtbase/src/widgets/kernel/qboxlayout.cpp.html#_ZN10QBoxLayout13insertSpacingEii
So if you want to have Expanding horizontal policy, you have to set it yourself. But if you look at the source code code of addStretch() - that's exactly what it does (creates QSpacerItem with size of 0 and expanding size policy).
Additionally, I figured out that I can 'glue' those two widgets together by setting the alignment of the QHBoxLayout to AlignHCenter.
In summary,
horLayout->setSpacing(0); horLayout->setAlignment(Qt::AlignHCenter);
should do the trick. Thank you very much again.
-
@Kenticent
Like I said, personally I find half of the Qt layout stuff guesswork/divine inspiration/brain-ache, and address it with trail-and-error/use the Designer till I get it right :)