Question

In a custom JavaFX UI Control, I want to place some text in the corners of the Control. Here is the source code from my Skin class:

double width = control.getWidth();
double height = control.getHeight();

Text test1Text = new Text(0, 0, "top left");
Text test2Text = new Text(0, height-1, "bottom left");
Text test3Text = new Text("top right");
test3Text.relocate(width - test3Text.getLayoutBounds().getWidth(), 0);
Text test4Text = new Text("bottom right");
test4Text.relocate(width - test4Text.getLayoutBounds().getWidth(), height-1);

Unfortunately, it seems to make a difference, whether I construct a text at a given co-ordinate or whether I construct it without co-ordinates and relocate it in place afterwards:

  • In the first case, the co-ordinate in the constructor will be the bottom-left co-ordinate of the text.
  • In the second case, the given co-ordinate will be the top-left co-ordinate.

Any ideas for this strange behaviour?

Was it helpful?

Solution

Text is being drawn from (0,0) position to the right and up. E.g. if you create new Text("Hello") and ask for it bounds you will see that they have negative vertical coordinates [minX:0.0, minY:-12.94921875]

The reason IMHO is next: Text is being drawn in Controls and they care more about baseline of the text. Imagine 2 buttons with text "water" and "Water" -- you would really expect them to be aligned by the baseline rather then top-left corner:

enter image description here

relocate() method from the other side works with a regular Nodes and operates layout which always calculated for top-left corner.

OTHER TIPS

Since JavaFX has been open sourced for the most of its parts, here is the codes for both (JavaFX 8)
javafx.scene.text.Text and javafx.scene.Node.
I could not examine in depth but it is obvious that the Text constructor and Node#relocate() are doing different things:
Text constructor

public Text(double x, double y, String text) {
    this(text);
    setX(x);
    setY(y);
}

Node#relocate()

public void relocate(double x, double y) {
        setLayoutX(x - getLayoutBounds().getMinX());
        setLayoutY(y - getLayoutBounds().getMinY());

        PlatformLogger logger = Logging.getLayoutLogger();
        if (logger.isLoggable(PlatformLogger.FINER)) {
            logger.finer(this.toString()+" moved to ("+x+","+y+")");
        }
}

That's all for my idea, sorry.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top