JavaFX 2 TextArea根据其内容更改高度

时间:2015-05-13 14:11:20

标签: java javafx javafx-2

在JavaFX 2.2中,有没有办法让TextArea(使用setWrapText(true)和常量maxWidth)根据内容改变其高度?

理想的行为:当用户在TextArea中键入内容时,当需要另一行时,它会调整大小,而当需要该行时,则会减少。

或者是否有更好的JavaFX控件可以在这种情况下使用?

2 个答案:

答案 0 :(得分:2)

您可以将文本区域的prefHeight绑定到其包含的文本的高度。这有点像黑客,因为您需要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);
    }
}

答案 1 :(得分:2)

要添加到James_D的答案中的两件事(因为我缺乏评论代表):

1)对于像36+这样的大字体,文本区域大小最初是错误的,但是当我在文本区域内单击时自我纠正。应用CSS后,您可以调用textArea.layout(),但在窗口最大化后,文本区域仍然不会立即调整大小。要解决此问题,请在对textArea.requestLayout()对象的本地边界进行任何更改后,在更改侦听器中异步调用Text。见下文。

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将侦听器lambdas替换为Change Listeners,并将空()-> lambdas替换为Runnable。)