Taking this code, shouldn't the word "Label" be on the right side of the application window?
To be more specific about my problem: Why doesn't the HBox.setHgrow
give the label all the horizontal space available?
package com.example.javafxwindow
import javafx.application.Application
import javafx.geometry.Pos
import javafx.scene.Scene
import javafx.scene.control.Label
import javafx.scene.layout.HBox
import javafx.scene.layout.Priority
import javafx.stage.Stage
class HelloApplication : Application()
{
override fun start(stage: Stage)
{
val label = Label("Label")
label.alignment = Pos.CENTER_RIGHT
HBox.setHgrow(label, Priority.ALWAYS)
val hbox = HBox(label)
val scene = Scene(hbox, 400.0, 400.0)
stage.scene = scene
stage.show()
}
}
fun main()
{
Application.launch(HelloApplication::class.java)
}
This is, slowly but surely, driving me nuts. I don't know what to do else. Maybe I'm blind by now ... where's the error?
I would really appreciate any help.
Allowing a label to grow beyond its preferred size
The label is bounded by its
maxWidth
which defaults to itsprefWidth
.You want to make the
maxWidth
unbounded, so call:Different controls have different defaults for
maxWidth
. For buttons and labels themaxWidth
default to theirprefWidth
. Unless you reset themaxWidth
these controls won't grow; even if you provide hints that you might think would make them do so.Quoting the Oracle JavaFX layout sizing tutorial:
It would be nice if this detail of information was also in java doc of each control, so you would know which controls default their max size to the pref size. There is some information on this in the
HBox
java doc.Spring alternative
An alternative is to insert a spring pane into the hbox before the label and set the hgrow on the spring pane instead. That will push the label all the way to the right. For info on that approach see:
Alternative layout
As noted by DaveB in the comments:
Example FXML
I don't write Kotlin, so I will provide a layout example with FXML instead and you can translate it to Kotlin if you wish.
The example sets the
maxWidth
of a label to a large number so that the label can grow to fill the available area, with the text in the label right aligned.FAQ
Just my opinion, others have different opinions:
It doesn't make a lot of sense to prefer something to be an infinite size, you could never see it at the preferred size.
It probably confused the layout algorithm. I'm guessing it sized the label to the preferred size, then needed to round it up to snap it for pixel alignment or add to the margin. This would cause a double overflow, making the preferred size negative, which doesn't make sense. So it would try to size to the minimum size instead. When there is not enough space to display a value, a label will elide the text (replacing characters with
...
), which is what it did here. The default minimum size will be just enough to display the elided text.If you also set
minSize
to 100 and theprefSize
toDouble.MAX_VALUE
, the label will show all of the text aligned within the minSize, which indicates that it is the minimum size that is being respected in such a case.Anyway, don't set the
prefWidth
toDouble.MAX_VALUE
. Instead, set themaxWidth
to some large number so that the field can grow to fit it (e.g.Integer.MAX_VALUE
).