JavaFX:如何滚动到textarea中的特定行
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaFX:如何滚动到textarea中的特定行相关的知识,希望对你有一定的参考价值。
package sample;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.stage.Stage;
import java.util.stream.IntStream;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
final StringBuilder sb = new StringBuilder();
IntStream.range(1, 100).forEach(i -> sb.append("Line " + i + "
"));
TextArea ta = new TextArea();
ta.setText(sb.toString());
//how to I get line 30 at top of the visible textarea
double someValue = 0;
ta.setScrollTop(someValue);
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(ta, 300, 300));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
如何在可见文本区域的顶部获得30行?我认为'someValue'应该相对于可以滚动的总高度但是可以滚动的总高度是多少
这是我想要实现的结果:
答案
这有点棘手。我们可以确定每个行高并调用ta.setScrollTop((line - 1) * lineHeight);
,但我们不知道TextArea
使用的行间距。
但是我发现TextAreaSkin
包含用于确定任何选定字符的边界的公共方法,我们只需要知道它的索引。
@Override
public void start(Stage primaryStage) throws Exception{
final StringBuilder sb = new StringBuilder();
IntStream.range(1, 100).forEach(i -> sb.append("Line " + i + "
"));
TextArea ta = new TextArea();
ta.setText(sb.toString());
// TextArea did not setup its skin yet, so we can't use it right now.
// We just append our task to the user tasks queue.
Platform.runLater(() -> {
// Define desired line
final int line = 30;
// Index of the first character in line that we look for.
int index = 0;
// for this example following line will work:
// int index = ta.getText().indexOf("Line " + line);
// for lines that do not contain its index we rely on "
" count
int linesEncountered = 0;
boolean lineFound = false;
for (int i = 0; i < ta.getText().length(); i++) {
// count characters on our way to our desired line
index++;
if(ta.getText().charAt(i) == '
') {
// next line char encountered
linesEncountered++;
if(linesEncountered == line-1) {
// next line is what we're looking for, stop now
lineFound = true;
break;
}
}
}
// scroll only if line found
if(lineFound) {
// Get bounds of the first character in the line using internal API (see comment below the code)
Rectangle2D lineBounds = ((com.sun.javafx.scene.control.skin.TextAreaSkin) ta.getSkin()).getCharacterBounds(index);
// Scroll to the top-Y of our line
ta.setScrollTop(lineBounds.getMinY());
}
});
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(ta, 300, 300));
primaryStage.show();
}
这个解决方案适用于Java 8,9+ TextAreaSkin
被移动到公共包,所以你需要做的一切就是用com.sun.javafx.scene.control.skin.TextAreaSkin
替换javafx.scene.control.skin.TextAreaSkin
以上是关于JavaFX:如何滚动到textarea中的特定行的主要内容,如果未能解决你的问题,请参考以下文章