JavaFX - 限制 TextArea 行?
Posted
技术标签:
【中文标题】JavaFX - 限制 TextArea 行?【英文标题】:JavaFX - Limit TextArea rows? 【发布时间】:2015-09-20 11:55:31 【问题描述】:在 Swing 中,我创建了一个自定义 Document,它能够确定和限制 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;
【问题讨论】:
.setPrefRowCount(10);
不起作用吗?将 wrapText 设置为 true? textarea 也尊重它的区域,所以它会努力填充它,除非你用 maxsize 或其他东西限制它
据我所知,setPrefRowCount 和 setPrefColCount 仅影响 TextArea 的首选大小,不限制内容。
这根本没有任何意义。你不能指望在你 e 时线路会受到限制。 G。使文本区域更小。这是可用性的噩梦。这有什么用例?
大小没有变化。假设一个 TextArea 定义为 10 行和 40 列。首选大小已设置并且不会更改,但在某些情况下,我希望将文本限制为 400 个字符和/或 10 行。 Text 节点被用作确定当前首选大小的帮助器,以便确定字段中当前有多少换行(因为换行时不存在换行)。很抱歉我一直在远离我的电脑并试图跟上我的手机。
所以如果你有 400 个字符,前 10 个字符是换行符,你只想有 10 个换行符,以防 textarea 缩小到 1 个字符的列宽?限制行数而不是限制字符数仍然没有任何意义。
【参考方案1】:
自 Java 8 Update 40 以来,每个 TextInputControl
都有一个 TextFormatter
用于此任务。
它有两个功能,其中一个可用于您的任务:
可以拦截和修改用户输入的过滤器(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
真的很强大,应该可以处理所有这些。
【讨论】:
我会在几个小时内调查这个问题。我相信hard(er) 部分正在计算由于文本在字段中换行而不是用户按下回车键的行数。我现在不在我的电脑附近,但我已经接近通过使用文本节点来解决这个问题了。 @Tommo 但是现在您完全改变了问题的范围......从“我如何(哪些方法,类文件)我可以限制 TextField 中的行数”到“如何确定数量TextField 中的行数".. 嗯,他们是齐头并进的,不是吗?确定行数几乎是能够限制行数的要求。 这取决于几件事。所以不一定,不。例如。我们从“行数”(这通常意味着由换行符分隔的字符串)变成了换行数.. 问题的第一行确实说明是换行还是按下了换行符。【参考方案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's 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;
【讨论】:
只是从这个页面复制/粘贴在一起,没有研究,不是你的解决方案。 建议使用 TextFormatter 是朝着正确方向迈出的一步,但是 getWrappedLines 方法是我最初发布的。将两者结合起来解决了这个问题。 我完全同意。我只是想我会发布似乎对我有用的东西,以防其他人遇到类似问题或更好的建议解决方案。【参考方案3】:简单的解决方案(未优化,仅在文本不太长时使用):
int maxRowCount = 3;
new TextArea().setTextFormatter (new TextFormatter<> (change ->
if (change.isContentChange ())
if (change.getControlNewText ().chars ().filter (a -> a == '\n').count () > maxRowCount - 1)
change.setText ("");
return change;
));
【讨论】:
以上是关于JavaFX - 限制 TextArea 行?的主要内容,如果未能解决你的问题,请参考以下文章
Javafx 8 替换 textarea 中的文本并保持格式