Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFX - Limit TextArea rows?

In Swing I created a custom Document which was able to determine and limit the number of rows in a TextArea whether a line was being wrapped or a line feed was pressed. I was hoping to find something similar in FX, but haven't been able to. Any suggestions for how to handle limiting the number of rows allowed?

Edit: This is how I was attempting to figure out how many wrapped lines are in the TextArea. The biggest issue is getting the exact width to pass into the setWrappingWidth because there seems to be some padding on the TextArea's content along with borders.

Text helper = new Text();
helper.setText(text);
helper.setFont(getFont());
helper.wrappingWidthProperty().bind(widthBinding);
Font font = getFont();
FontMetrics fontMetrics = Toolkit.getToolkit().getFontLoader().getFontMetrics(font);
int preferredHeight = new Double(helper.getLayoutBounds().getHeight()).intValue();
int lineHeight = new Double(fontMetrics.getMaxAscent() + fontMetrics.getMaxDescent()).intValue();
System.err.println("preferredHeight / lineHeight: " + preferredHeight / lineHeight);
return preferredHeight / lineHeight;
like image 787
Tommo Avatar asked Jul 02 '15 19:07

Tommo


1 Answers

Every TextInputControl got a TextFormatter for this task since Java 8 Update 40.

It has two functionalities of which this one can be used for your Task:

A filter (getFilter()) that can intercept and modify user input. This helps to keep the text in the desired format.

This is a very primitive attempt to solve this:

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        BorderPane root = new BorderPane();

        final TextArea textArea = new TextArea();
        textArea.setTextFormatter(createTextFormatter());
        root.setCenter(textArea);

        primaryStage.setScene(new Scene(root, 400, 400));
        primaryStage.show();
    }

    private static <T> TextFormatter<T> createTextFormatter() {

        final IntegerProperty lines = new SimpleIntegerProperty(1);

        return new TextFormatter<>(change -> {
            if (change.isAdded()) {
                if (change.getText().indexOf('\n') > -1) {
                    lines.set(lines.get() + 1);
                }
                if (lines.get() > 10) {
                    change.setText("");
                }
            }
            return change;
        });
    }

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

This successfully prevents the user from entering more than 10 lines. But you should improve this solution, for example to handle:

  • text was replaced
  • text was deleted

The TextFormatter is really powerful and should be able to handle all this.

like image 175
eckig Avatar answered Oct 22 '22 19:10

eckig