5

Let's say I already have a Shape on the screen. For example:

Circle circle = new Circle(x, y, radius);
circle.setFill(Color.YELLOW);
root.getChildren().add(circle);

I would like to create a Label "over" that Circle such that the Label is centered in the Circle, the font size is maximized to fit inside the Circle, etc.

I can see how this could be accomplished via binding, but that seems needlessly complicated if the position/size of these things will never change during runtime.

Thank you in advance for your help! I'm very new to JavaFX and not all that experienced at programming in the first place, so I apologize if I should've been able to find this out via my research.

Basium
  • 53
  • 1
  • 1
  • 3

2 Answers2

10

Use a StackPane to automatically center the text on top of the shape.

spot

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.*;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.*;
import javafx.stage.Stage;

// java 8 code.
public class Circular extends Application {
    public static void main(String[] args) throws Exception {
        launch(args);
    }

    @Override
    public void start(final Stage stage) throws Exception {
        Text   text   = createText("Xyzzy");
        Circle circle = encircle(text);

        StackPane layout = new StackPane();
        layout.getChildren().addAll(
                circle,
                text
        );
        layout.setPadding(new Insets(20));

        stage.setScene(new Scene(layout));
        stage.show();
    }

    private Text createText(String string) {
        Text text = new Text(string);
        text.setBoundsType(TextBoundsType.VISUAL);
        text.setStyle(
                "-fx-font-family: \"Times New Roman\";" +
                "-fx-font-style: italic;" +
                "-fx-font-size: 48px;"
        );

        return text;
    }

    private Circle encircle(Text text) {
        Circle circle = new Circle();
        circle.setFill(Color.ORCHID);
        final double PADDING = 10;
        circle.setRadius(getWidth(text) / 2 + PADDING);

        return circle;
    }

    private double getWidth(Text text) {
        new Scene(new Group(text));
        text.applyCss();

        return text.getLayoutBounds().getWidth();
    }
}

Related

The answer to the related question discusses different bounds types for text (such as Visual bounds), in case you need that.

Community
  • 1
  • 1
jewelsea
  • 150,031
  • 14
  • 366
  • 406
  • Thank you very much for the solution - I also learned a few extra JavaFX features from this! – Basium Apr 25 '14 at 03:06
0
StackPane stackPane = new StackPane();
Circle circle = new Circle();
Label label = new Label("Hi");
circle.setFill(Color.GOLD);
circle.setStroke(Color.GRAY);
circle.radiusProperty().bind(label.widthProperty());
stackPane.getChildren().addAll(circle, label);
Carlos Eduardo
  • 740
  • 6
  • 10