JavaFX2文本区域,根据其内容更改高度

JavaFX2文本区域,根据其内容更改高度,java,javafx,javafx-2,Java,Javafx,Javafx 2,在JavaFX2.2中,是否有任何方法可以使带有setWrapTexttrue和常量maxWidth的TextArea根据内容更改其高度 期望的行为:当用户在文本区域内键入内容时,当需要另一行时,它会调整大小,当不再需要该行时,它会减小大小 或者有更好的JavaFX控件可以在这种情况下使用吗?您可以将文本区域的高度绑定到它包含的文本的高度。这是一个小技巧,因为您需要查找以获取文本区域中包含的文本,但它似乎可以工作。您需要确保在应用CSS后查找文本节点。通常这意味着在它出现在屏幕上之后 impor

在JavaFX2.2中,是否有任何方法可以使带有setWrapTexttrue和常量maxWidth的TextArea根据内容更改其高度

期望的行为:当用户在文本区域内键入内容时,当需要另一行时,它会调整大小,当不再需要该行时,它会减小大小

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

您可以将文本区域的高度绑定到它包含的文本的高度。这是一个小技巧,因为您需要查找以获取文本区域中包含的文本,但它似乎可以工作。您需要确保在应用CSS后查找文本节点。通常这意味着在它出现在屏幕上之后

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);
    }
}
可以将文本区域的高度绑定到它包含的文本的高度。这是一个小技巧,因为您需要查找以获取文本区域中包含的文本,但它似乎可以工作。您需要确保在应用CSS后查找文本节点。通常这意味着在它出现在屏幕上之后

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,但在窗口最大化后,文本区域仍然不会立即调整大小。要解决此问题,请在对文本对象的本地边界进行任何更改后,在更改侦听器中异步调用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());
                });
            }
        });
    }
}

上面的代码是为Java8编译的。对于Java 7,根据JavaFX API将侦听器lambda替换为Change Listeners,并将empty->lambda替换为Runnable。

James_D的回答中需要添加两件事,因为我没有评论的代表:

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

上面的代码是为Java8编译的。对于Java 7,根据JavaFX API将侦听器lambda替换为Change Listeners,并将empty->lambda替换为Runnable。

您确定文本区域的大小会增加或减少而不是显示滚动条吗?滚动条会显示。;]我希望它增加和减少。你确定文本区域的大小会增加和减少,而不是显示滚动条吗?滚动条会显示。;]我想让它增加和减少。它很粗糙。我正在编写一个UI,它在整个应用程序的不同位置使用,通常作为更大的UI图的一部分,并不总是附加到根目录上,并且是可见的。您的方法依赖于猜测UI状态和绑定时刻,因此我担心这是不可能的。不过,谢谢你的建议!更新后的版本可能会让它更灵活,更黑客,不过。。。?。因为您标记了这个javafx-2,所以还删除了lambdas。因为在这个问题上似乎没有更多的活动,我将接受您的回答。这是一个聪明的方法,更重要的是——它有效。但老实说,我希望将来有人会发布一个更干净的…这是相当黑客。我正在编写一个UI,它在整个应用程序的不同位置使用,通常作为更大的UI图的一部分,并不总是附加到根目录上,并且是可见的。您的方法依赖于猜测UI状态和绑定时刻,因此我担心这是不可能的。不过,谢谢你的建议!更新后的版本可能会让它更灵活,更黑客,不过。。。?。因为您标记了这个javafx-2,所以还删除了lambdas。因为在这个问题上似乎没有更多的活动,我将接受您的回答。这是一个聪明的方法,更重要的是——它有效。但老实说,我希望将来有人会发布一个更干净的。。。