Подтвердить что ты не робот

JavaFX - лимит строк TextArea?

В Swing я создал собственный документ, который смог определить и ограничить количество строк в TextArea, была ли строка завернута или была нажата строка. Я надеялся найти что-то подобное в FX, но не смог. Любые предложения о том, как обращаться с ограничением количества разрешенных строк?

Изменить: Вот как я пытался выяснить, сколько строк завершено в TextArea. Самая большая проблема заключается в том, чтобы получить точную ширину, чтобы перейти в setWrappingWidth, потому что, кажется, есть некоторое дополнение к содержимому TextArea вместе с границами.

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;
4b9b3361

Ответ 1

Каждый TextInputControl получил TextFormatter для этой задачи, поскольку Java 8 Update 40.

Он имеет две функции, из которых этот может быть использован для вашей задачи:

Фильтр (getFilter()), который может перехватывать и изменять ввод пользователя. Это помогает сохранить текст в нужном формате.

Это очень примитивная попытка решить эту проблему:

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);
    }
}

Это успешно предотвращает ввод пользователем более 10 строк. Но вы должны улучшить это решение, например, для обработки:

  • текст был заменен
  • текст удален.

TextFormatter действительно мощный и должен иметь возможность обрабатывать все это.

Ответ 2

Назначение TextFormatter через:

setTextFormatter(new TextFormatter<>(change -> {
  if(change.isContentChange()) {
    if(getWrappedLines(change.getControlText(), change.getControlNewText()) > maxRows) {
      change.setText("");
    }
  }
  return change;
}));

И метод getWrappedLines:

int getWrappedLines(String oldText, String newText) {
  Text helper = (Text)lookup(".text");
  if(helper != null) {
    helper.setText(newText);
    FontMetrics fontMetrics = Toolkit.getToolkit().getFontLoader().getFontMetrics(getFont());
    int preferredHeight = new Double(helper.getLayoutBounds().getHeight()).intValue();
    int lineHeight = new Double(fontMetrics.getLineHeight()).intValue();
    // Initially a line preferredHeight = 14, however each new line seems   to increase the preferredHeight by
    // 16 instead of 14.
    preferredHeight = preferredHeight == lineHeight ? preferredHeight : preferredHeight - 2;
    helper.setText(oldText);
    return preferredHeight / lineHeight;
  }
  else {
    return 0;
  }

}