如何进行TextArea拉伸以填充内容,在过程中扩展父级?

Dan*_*son 17 javafx-2 javafx-8

所以我有一个TextArea,当用户将段落粘贴到其中,或者只是在其中写入时,我希望它垂直展开以显示所有可用的文本.即不要在文本字段本身使用滚动条...就像许多网页上发生的情况一样.包括我自己在内的许多用户不喜欢被迫在一个小窗口中进行编辑.究竟Facebook状态更新框如何工作.

我试过了

myTextArea.autoSize()
Run Code Online (Sandbox Code Playgroud)

裹着一个

myTextArea.textProperty().addListener(new ChangeListener()....);

但这不起作用.我认为它很高兴自动调整到目前的大小.

左,右和顶部锚点设置为它的父级AnchorPane.我尝试了底部连接而没有连接.理想情况下,我希望随着textarea的增长而增长锚定窗格.

我不介意阅读TextProperty并计算我自己设置的触发器大小......但如果已经有最佳实践,这似乎是一种hacky方法.javafx的属性和子对象的数量是令人畏惧的,这似乎是一个在这里提出问题的好点,而不是试图弄清楚字体/段落占用了多少像素.

更新:

所以我想也许我是在思考它,而我所要做的就是关掉滚动条,剩下的就会发生.唉,寻找"滚动","垂直","vbar"的可用字段和方法,我找不到任何可以使用的东西.ScrollTopProperty看起来像是其他东西.

Ulu*_*Biy 13

问题; 当文本通过用户的输入或复制粘贴而改变时,textArea的高度需要增长或缩小.这是另一种方法:

public class TextAreaDemo extends Application {

    private Text textHolder = new Text();
    private double oldHeight = 0;

    @Override
    public void start(Stage primaryStage) {
        final TextArea textArea = new TextArea();
        textArea.setPrefSize(200, 40);
        textArea.setWrapText(true);

        textHolder.textProperty().bind(textArea.textProperty());
        textHolder.layoutBoundsProperty().addListener(new ChangeListener<Bounds>() {
            @Override
            public void changed(ObservableValue<? extends Bounds> observable, Bounds oldValue, Bounds newValue) {
                if (oldHeight != newValue.getHeight()) {
                    System.out.println("newValue = " + newValue.getHeight());
                    oldHeight = newValue.getHeight();
                    textArea.setPrefHeight(textHolder.getLayoutBounds().getHeight() + 20); // +20 is for paddings
                }
            }
        });

        Group root = new Group(textArea);
        Scene scene = new Scene(root, 300, 250);
        primaryStage.setScene(scene);
        primaryStage.show();

        //  See the explanation below of the following line. 
        //  textHolder.setWrappingWidth(textArea.getWidth() - 10);  // -10 for left-right padding. Exact value can be obtained from caspian.css
    }

    public static void main(String[] args) {
        launch(args);
    }
}
Run Code Online (Sandbox Code Playgroud)

但它有一个缺点; 只有在多行之间有换行符(即输入键)时,textarea的高度才会改变,如果用户键入的时间足够长,则文本会被换行到多行,但高度不会改变.

为了解决这个缺点,我添加了这一行

textHolder.setWrappingWidth(textArea.getWidth() - 10);
Run Code Online (Sandbox Code Playgroud)

之后primaryStage.show();.它适用于用户不进行换行的长打字.然而,这会产生另一个问题 当用户通过点击"退格"删除文本时,会发生此问题.当textHolder高度发生更改且textArea的高度设置为新值时,会出现问题.IMO它可能是一个bug,没有更深入地观察.

在这两种情况下,复制粘贴都正确处理.


gon*_*ard 7

等待更好,我使用这个hacky解决方案.

  • 查找textarea的垂直滚动条.
  • 让它透明
  • 听听它的可见财产
  • 当滚动条变为可见时,我向textarea添加一行.

代码:

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ScrollBar;
import javafx.scene.control.TextArea;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class GrowGrowTextArea extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        AnchorPane root = new AnchorPane();
        root.setStyle("-fx-padding:20;-fx-background-color:dodgerblue;");
        final TextArea textArea = new TextArea();
        AnchorPane.setTopAnchor(textArea, 10.0);
        AnchorPane.setLeftAnchor(textArea, 10.0);
        AnchorPane.setRightAnchor(textArea, 10.0);
        root.getChildren().add(textArea);
        primaryStage.setScene(new Scene(root, 400, 300));
        primaryStage.show();
        ScrollBar scrollBar = lookupVerticalScrollBar(textArea);
        scrollBar.setOpacity(0.0);
        scrollBar.visibleProperty().addListener(new ChangeListener<Boolean>() {

            @Override
            public void changed(ObservableValue<? extends Boolean> source,
                                Boolean wasVisible,
                                Boolean isVisible) {
                if (isVisible) {
                    textArea.setPrefRowCount(textArea.getPrefRowCount() + 1);
                    textArea.requestLayout();
                }
            }
        });

    }

    private ScrollBar lookupVerticalScrollBar(Node node) {
        if (node instanceof ScrollBar && ((ScrollBar)node).getOrientation() == Orientation.VERTICAL) {
            return (ScrollBar) node;
        }
        if (node instanceof Parent) {
            ObservableList<Node> children = ((Parent) node).getChildrenUnmodifiable();
            for (Node child : children) {
                ScrollBar scrollBar = lookupVerticalScrollBar(child);
                if (scrollBar != null) {
                    return scrollBar;
                }
            }
        }
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)