I want to display a rectangle that contains a text/label. For this purpose I created a stackpane and added a rectangle and a label to it. However the text/label is not centered correctly. It is placed outside of the rectangle (to the left). This is the code I am currently using:
createRectangle(String name) {
pane = new StackPane();
text = new Label(name);
rect = new Rectangle();
// bind rectangle width to text width and add 10
rect.widthProperty().bind(text.widthProperty().add(10));
rect.heightProperty().bind(text.heightProperty().add(10));
// add to stackpane
pane.getChildren().addAll(rect,text);
// display stackpane
getChildren().add(pane)
}
I have tried binding the xProperty() and yProperty() of the rectangle, changing the alignment of the stackpane (setAlignment(Pos.CENTER)) and other things, but without success.
When I use a fixed rectangle size (e.g. new Rectangle(30,30)) and do not use the bindings, the label is centered correctly within the rectangle. However, the rectangle's size needs to adjust depending on the label size:
// label is placed correctly in the center of the rectangle
createRectangle(String name) {
pane = new StackPane();
text = new Label(name);
rect = new Rectangle(30,30);
// add to stackpane
pane.getChildren().addAll(rect,text);
// display stackpane
getChildren().add(pane)
}
For a Background Sized to the Label
Just use CSS directly on the Label, you don't need any other nodes.
The padding can be used to adjust the size of the rectangular background area around the label.
For a Resizable Background
You don't need a Rectangle node, put the label in a StackPane and set a background on the StackPane:
Executable sample
Note: Inline styles in this answer are just for easy demonstration purposes, best practice is to use a CSS stylesheet for CSS style definitions.
Yes, anything which derives from Region (which includes layout panes such as StackPane and Controls such as Label), can be styled pretty extensively via CSS.
To get a rounded background, you can use
-fx-background-radius
.To get an arbitrary shaped background, you can use
fx-shape
, though you may find it tricky to position your text within the arbitrarily shaped background.You can also write a shape in code and use bindings to make things fit inside it as you originally tried in your question.
If things need a lot of fine-tuning then you can subclass region and over-ride the layoutChildren method to perform precise layout calculations for all of the children inside that method (this is the way that most of the in-built JavaFX controls handle layouts in their skin classes).
Anyway, a seemingly simple question doesn't always have a simple answer, because there ends up lots of variations both in the way you can do things and many subtle differences in what you might want to do, such as how to handle wrapped text, insets, whether to elide the text beyond a minimum size, etc.
However, for the most common tasks of rectangular or rounded rectangular backgrounds, I'd just stick to using CSS styles directly on labels. By using style sheets, you can easily completely change the app style for your labels.
Here is a more extensive, overkill sample:
LabelBackground.java
label-styles.css
If you are super-keen for further samples, look at the way the QuoteMaker app handles styling of resizable label backgrounds.