JavaFX 2 TextArea 根据其内容改变高度
JavaFX 2 TextArea that changes height depending on its contents
在 JavaFX 2.2 中,是否有任何方法可以使 TextArea(使用 setWrapText(true) 和常量 maxWidth)根据内容改变其高度?
期望的行为:当用户在 TextArea 中输入内容时,它会在需要另一行时调整大小,而在不再需要该行时缩小。
或者是否有更好的 JavaFX 控件可用于这种情况?
您可以将文本区域的 prefHeight
绑定到它包含的文本的高度。这有点 hack,因为您需要 lookup
来获取文本区域中包含的文本,但它似乎可以工作。您需要确保在应用 CSS 之后查找 text
节点。 (通常这意味着它出现在屏幕上之后...)
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ResizingTextArea extends Application {
@Override
public void start(Stage primaryStage) {
TextArea textArea = new TextArea();
textArea.setWrapText(true);
textArea.sceneProperty().addListener(new ChangeListener<Scene>() {
@Override
public void changed(ObservableValue<? extends Scene> obs, Scene oldScene, Scene newScene) {
if (newScene != null) {
textArea.applyCSS();
Node text = textArea.lookup(".text");
textArea.prefHeightProperty().bind(Bindings.createDoubleBinding(new Callable<Double>() {
@Override
public Double call() {
return 2+text.getBoundsInLocal().getHeight();
}
}), text.boundsInLocalProperty()));
}
}
});
VBox root = new VBox(textArea);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
要添加到 James_D 的回答中的两件事(因为我没有代表发表评论):
1) 对于像 36+ 这样的大字体,一开始文本区域的大小是错误的,但当我在文本区域内单击时会自行更正。您可以在应用 CSS 后调用 textArea.layout()
,但在 window 最大化后文本区域仍然不会立即调整大小。要解决此问题,请在对 Text
对象的本地边界进行任何更改后在更改侦听器中异步调用 textArea.requestLayout()
。见下文。
2) 文本区域仍然短了几个像素,滚动条仍然可见。如果您在绑定中将 2
替换为 textArea.getFont().getSize()
,则无论字体大小是小还是大,高度都非常适合文本。
class CustomTextArea extends TextArea {
CustomTextArea() {
setWrapText(true);
setFont(Font.font("Arial Black", 72));
sceneProperty().addListener((observableNewScene, oldScene, newScene) -> {
if (newScene != null) {
applyCss();
Node text = lookup(".text");
// 2)
prefHeightProperty().bind(Bindings.createDoubleBinding(() -> {
return getFont().getSize() + text.getBoundsInLocal().getHeight();
}, text.boundsInLocalProperty()));
// 1)
text.boundsInLocalProperty().addListener((observableBoundsAfter, boundsBefore, boundsAfter) -> {
Platform.runLater(() -> requestLayout());
});
}
});
}
}
(以上编译为Java 8。对于Java 7,根据JavaFX API,用Change Listeners替换listener lambdas,并替换带有 Runnable
的空 ()->
lambda。)
在 JavaFX 2.2 中,是否有任何方法可以使 TextArea(使用 setWrapText(true) 和常量 maxWidth)根据内容改变其高度?
期望的行为:当用户在 TextArea 中输入内容时,它会在需要另一行时调整大小,而在不再需要该行时缩小。
或者是否有更好的 JavaFX 控件可用于这种情况?
您可以将文本区域的 prefHeight
绑定到它包含的文本的高度。这有点 hack,因为您需要 lookup
来获取文本区域中包含的文本,但它似乎可以工作。您需要确保在应用 CSS 之后查找 text
节点。 (通常这意味着它出现在屏幕上之后...)
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ResizingTextArea extends Application {
@Override
public void start(Stage primaryStage) {
TextArea textArea = new TextArea();
textArea.setWrapText(true);
textArea.sceneProperty().addListener(new ChangeListener<Scene>() {
@Override
public void changed(ObservableValue<? extends Scene> obs, Scene oldScene, Scene newScene) {
if (newScene != null) {
textArea.applyCSS();
Node text = textArea.lookup(".text");
textArea.prefHeightProperty().bind(Bindings.createDoubleBinding(new Callable<Double>() {
@Override
public Double call() {
return 2+text.getBoundsInLocal().getHeight();
}
}), text.boundsInLocalProperty()));
}
}
});
VBox root = new VBox(textArea);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
要添加到 James_D 的回答中的两件事(因为我没有代表发表评论):
1) 对于像 36+ 这样的大字体,一开始文本区域的大小是错误的,但当我在文本区域内单击时会自行更正。您可以在应用 CSS 后调用 textArea.layout()
,但在 window 最大化后文本区域仍然不会立即调整大小。要解决此问题,请在对 Text
对象的本地边界进行任何更改后在更改侦听器中异步调用 textArea.requestLayout()
。见下文。
2) 文本区域仍然短了几个像素,滚动条仍然可见。如果您在绑定中将 2
替换为 textArea.getFont().getSize()
,则无论字体大小是小还是大,高度都非常适合文本。
class CustomTextArea extends TextArea {
CustomTextArea() {
setWrapText(true);
setFont(Font.font("Arial Black", 72));
sceneProperty().addListener((observableNewScene, oldScene, newScene) -> {
if (newScene != null) {
applyCss();
Node text = lookup(".text");
// 2)
prefHeightProperty().bind(Bindings.createDoubleBinding(() -> {
return getFont().getSize() + text.getBoundsInLocal().getHeight();
}, text.boundsInLocalProperty()));
// 1)
text.boundsInLocalProperty().addListener((observableBoundsAfter, boundsBefore, boundsAfter) -> {
Platform.runLater(() -> requestLayout());
});
}
});
}
}
(以上编译为Java 8。对于Java 7,根据JavaFX API,用Change Listeners替换listener lambdas,并替换带有 Runnable
的空 ()->
lambda。)