Reputation: 1542
In the QML below, I have three items in a row layout with each item needing to be centered vertically in that layout.
The middle item is a PlayerSelector
, which creates a varying number of text edit boxes to change the name of each player. I've tried two different ways to keep the PlayerSelector
vertically centered. The one that works for me causes a runtime warning, the suggested method doesn't keep that item centered vertically. See these screen caps and the code below:
Method 1&2 both center initially
Method 1 correctly maintains vertical centering (anchors.verticalCenter
)
Method 2 does not maintain vertical centering (Layout.alignment
)
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
Item {
id: gameStart
anchors.top: parent.top
height: parent.height
width: parent.width
signal playGame
RowLayout {
id: layout
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
RoundButton {
id: playButton
text: "Play"
width: 40
radius: 2
font.pointSize: 12
onClicked: {
var players = selector.playerArray
for (var i =0; i < players.count; i++) {
console.log(players.itemAt(i).playerName)
game.addPlayer(players.itemAt(i).playerName)
}
gameStart.playGame()
}
}
PlayerSelector {
id: selector
// Layout.alignment: Qt.AlignVCenter // method 2
anchors.verticalCenter: layout.verticalCenter // method 1
}
RoundButton {
id: quitButton
text: "Quit"
width: 40
radius: 2
font.pointSize: 12
onClicked: {
game.quit()
}
}
}
}
The problem with method 1 is that although it works, it shows this runtime warning:
qrc:/qml/GameStart.qml:41:9: QML PlayerSelector: Detected anchors on an item that is managed by a layout. This is undefined behavior; use Layout.alignment instead.
Is there a way to get the alignment I'm after but not have the runtime warning? I'm worried about the undefined behavior
part.
Upvotes: 0
Views: 2425
Reputation: 2671
Alignment only works when the Layout size is bigger than the item size. So for example if layout's height
is 200 and item's height
is 100, then when you align vertically, the item will have 50 pixels on either side. But if the item is also 200 pixels, then it just fills it. In your case the PlayerSelector
has the same height
as the RowLayout
, and is therefore aligned. The other items are not aligned in this case.
IMO there are two approaches in sizing a layout and its children:
1- Explicit sizes go from parents to children: you explicitly specify the size for the layout, and the size of children is relative to the size of layout. This is my personal preference since it is easier to make sure everything is sized and aligned correctly. When screen is resized things just shrink or stretch proportionately. In this approach only use Layout
attached properties for both size and alignment.
2- Size of layout is implicitly defined from the size of the child items. (your approach) This approach can be more flexible and give you non-stretched but functional layouts when screen size changes, but there are more degrees of freedom for things to go wrong when screen is resized. In this approach, you can use (preferably) implicit or explicit sizes for children, but alignment still should be handled by Layout
attached properties.
In your case it seems that the layout's height
is set to the height
of PlayerSelector
(the largest height
), so the other items are at the top of their row placement, and PlayerSelector
is actually the only item that is vertically centered (it fills the whole height
). So you could set alignment for all other items as well to make sure everything is centered.
Upvotes: 3