Reputation: 488
I've encountered a very strange set of circumstances with text wrapping and centered alignment in a JavaFX label. I'm sure I'm doing something wrong or ill-advised, but I cannot seem to figure out what I'm doing wrong.
Basically, I'm attempting to put a title over a tile pane, and have that title be centered. Also, when the window is resized, I'd like the title to wrap. The strangeness comes in when the title is not wrapped (e.g.: one line), it isn't centered any more. As soon as it wraps, it centers again. Here's some sample code that produces the effect:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.TilePane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.apache.commons.lang.RandomStringUtils;
public class Foo extends Application
{
@Override
public void start(Stage primaryStage) throws Exception
{
TilePane panel = new TilePane();
panel.setTileAlignment(Pos.CENTER_LEFT);
for (int i = 0; i < 25; i++)
{
panel.getChildren().add(new Label(RandomStringUtils.randomAlphabetic(10)));
}
Label title = new Label("Lorem ipsum dolor sit amet, consectetur adipiscing elit");
title.setStyle("-fx-font-size: 16; -fx-font-weight: bold; -fx-wrap-text:true; -fx-text-alignment: center -fx-border-color:black;");
title.minWidthProperty().bind(Bindings.add(-30, primaryStage.widthProperty()));
title.setTextAlignment(TextAlignment.CENTER);
VBox box = new VBox(title, panel);
box.setPadding(new Insets(10));
primaryStage.setScene(new Scene(box, 400, 400));
primaryStage.show();
}
public static void main(String[] args)
{
launch(args);
}
}
Here's a screenshot of what I'm seeing. In the first one, the bold line on top is centered and wrapped. In the second one, the bold line on top is not wrapped, and is left-aligned.
Upvotes: 2
Views: 5914
Reputation: 209319
As stated in the documentation, the text alignment controls the alignment of multi-line text. This is exactly the specified behavior.
If you imagine a rectangle that bounds all the text, when the text has multiple lines a decision has to be made as to how these individual lines are laid out within that rectangle. This is controlled by the textAlignment
property. The default is to align each line to the left of that box: you can also center, right-align, or justify (expand each line to fill the box). Another way to think of this is that the textAlignment
only controls the position of each line of text relative to the other lines of text.
On the other hand, the alignment
property defines how the content of the label (text and graphic) is aligned within the label itself, if there is more space in the label than the text occupies. So to center the label in your VBox
you first need to ensure the label fills the complete width of the VBox
, and then you need to set the alignment
property to CENTER
. You do the former by setting the maxWidth
of the label so that it grows indefinitely, and setting the fillWidth()
property of the VBox
to true
.
Using Java this looks like
public void start(Stage primaryStage) throws Exception
{
TilePane panel = new TilePane();
panel.setTileAlignment(Pos.CENTER_LEFT);
for (int i = 0; i < 25; i++)
{
panel.getChildren().add(new Label(randomAlphabetic(10)));
}
Label title = new Label("Lorem ipsum dolor sit amet, consectetur adipiscing elit");
title.setStyle("-fx-font-size: 16; -fx-font-weight: bold; -fx-wrap-text:true; -fx-border-color:black;");
title.setPadding(new Insets(5));
title.setAlignment(Pos.CENTER);
title.setMaxWidth(Double.MAX_VALUE);
title.setTextAlignment(TextAlignment.CENTER);
VBox box = new VBox(title, panel);
box.setFillWidth(true);
box.setPadding(new Insets(10));
primaryStage.setScene(new Scene(box, 400, 400));
primaryStage.show();
}
and you can set these properties in CSS if you prefer:
@Override
public void start(Stage primaryStage) throws Exception
{
TilePane panel = new TilePane();
panel.setTileAlignment(Pos.CENTER_LEFT);
for (int i = 0; i < 25; i++)
{
panel.getChildren().add(new Label(randomAlphabetic(10)));
}
Label title = new Label("Lorem ipsum dolor sit amet, consectetur adipiscing elit");
title.setStyle("-fx-font-size: 16; -fx-font-weight: bold; -fx-wrap-text:true; -fx-border-color:black;"
+ "-fx-text-alignment: center; -fx-alignment: center; -fx-max-width:Infinity; -fx-padding: 5;");
VBox box = new VBox(title, panel);
box.setFillWidth(true); // or box.setStyle("-fx-fill-width: true ;")
box.setPadding(new Insets(10));
primaryStage.setScene(new Scene(box, 400, 400));
primaryStage.show();
}
Upvotes: 6
Reputation: 818
Allright i try a some different tacticts and I figured it out with regular css. You can use the "-fx-alignment: center;" to do it. See this link for more information about which kind of css to use. Also the width of the label is important, else the width will just be the length of the text and there would be nothing to really center.
Making the changes, your code will look like this
@Override
public void start(Stage primaryStage) throws Exception
{
TilePane panel = new TilePane();
panel.setTileAlignment(Pos.CENTER_LEFT);
for (int i = 0; i < 25; i++)
{
panel.getChildren().add(new Label(RandomStringUtils.randomAlphabetic(10)));
}
Label title = new Label("Lorem ipsum dolor sit amet, consectetur adipiscing elit");
title.setStyle("-fx-font-size: 16; -fx-font-weight: bold; -fx-wrap-text:true; -fx-alignment: center; -fx-border-color:black;");
title.setMinWidth(400); //This is important, else the width will just be the text's length
VBox box = new VBox(title, panel);
box.setPadding(new Insets(10));
primaryStage.setScene(new Scene(box, 400, 400));
primaryStage.show();
}
public static void main(String[] args)
{
launch(args);
}
Upvotes: -1