Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFX TextArea Vertical Alignment

I'm trying to center the text in a text box in the middle of the text box, vertically. I've been able to center the text horizontally in java by using textArea.setStyle("-fx-text-alignment: center");.

I thought about the possibility of using parameters like Center Center or Bottom Center to achieve these results through the -fx-text-alignment string, but I'm handling the horizontal and vertical alignment through two different buttons on my window, and would therefore not want to implement logic to relate the two methods.

I have tried to toggle the -fx-alignment of the textArea as well, without any success.

Does anyone have any ideas on how I could get my text to appear in the vertical center of the textArea?

EDIT: Below is my current window, the text area I am attempting to manipulate is in the center.

enter image description here

like image 480
dibiasem Avatar asked Mar 13 '26 14:03

dibiasem


1 Answers

I can only find a solution to this by some brutally ugly hacking of the layout of the text area using some CSS lookups and listeners on the sizes of various child nodes of the text area.

Perhaps someone can come up with something more robust, but I don't see any way into this with the API.

Here's an example that works:

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.geometry.Bounds;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextArea;
import javafx.scene.shape.Path;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class TextAreaAlignment extends Application {

    @Override
    public void start(Stage primaryStage) {
        TextArea textArea = new TextArea();

        Scene scene = new Scene(textArea, 400, 400);

        hackTextAreaLayout(textArea);


        scene.getStylesheets().add("style.css");
        primaryStage.setScene(scene);
        primaryStage.show();


    }

    private void hackTextAreaLayout(TextArea textArea) {
        textArea.applyCss();
        textArea.layout();

        ScrollPane textAreaScroller = (ScrollPane) textArea.lookup(".scroll-pane");
        Text text = (Text) textArea.lookup(".text");


        ChangeListener<? super Bounds> listener = 
                (obs, oldBounds, newBounds) -> centerTextIfNecessary(textAreaScroller, text);
        textAreaScroller.viewportBoundsProperty().addListener(listener);
        text.boundsInLocalProperty().addListener(listener);

    }

    private void centerTextIfNecessary(ScrollPane textAreaScroller, Text text) {
        double textHeight = text.getBoundsInLocal().getHeight();
        double viewportHeight = textAreaScroller.getViewportBounds().getHeight();
        double offset = Math.max(0, (viewportHeight - textHeight) / 2 );
        text.setTranslateY(offset);
        Parent content = (Parent)textAreaScroller.getContent();
        for (Node n : content.getChildrenUnmodifiable()) {
            if (n instanceof Path) { // caret
                n.setTranslateY(offset);
            }
        }
    }



    public static void main(String[] args) {
        launch(args);
    }
}

style.css just has

.text-area .text {
    -fx-text-alignment: center ;
}

For reasons I can't quite grasp, this doesn't work at all if there is no style sheet attached.

like image 68
James_D Avatar answered Mar 16 '26 03:03

James_D



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!