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;
Ответы
Ответ 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;
}
}