当前位置: 首页 > 知识库问答 >
问题:

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

曾典
2023-03-14

所以我有一个文本区,当用户在里面粘贴段落,或者只是在里面书写时,我希望它垂直扩展以显示所有可用的文本。即不在文本字段本身中使用滚动条...就像很多网页上发生的一样。许多用户,包括我自己,不喜欢被迫在一个小窗口中编辑。脸书状态更新盒的工作原理。

我试过了

myTextArea.autoSize()

包裹在

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

但那不管用。我认为它很高兴自动调整到目前的大小。

左边,右边

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

更新:

所以我想可能是我想多了,我需要做的就是关掉滚动条,剩下的事情就会发生了。唉,寻找可用于“滚动”、“垂直”、“vbar”的字段和方法时,我什么也用不上。ScrollTopProperty看起来是为了别的东西。

共有3个答案

钦海荣
2023-03-14

我在创建扩展TextArea时也遇到了类似的问题。我正在创建看起来像TextField的TextArea,并且每次当没有更多空间时都会垂直扩展。我已经测试了在堆栈和其他可用来源上可以找到的关于此主题的所有解决方案。我发现很少有好的解决方案,但都不够好。

经过几个小时的战斗,我想出了这个办法。

我扩展了TextArea类,覆盖了layoutChildren()方法,并在文本高度上添加了一个监听器。

  @Override
  protected void layoutChildren() {
    super.layoutChildren();
    setWrapText(true);
    addListenerToTextHeight();
  }

  private void addListenerToTextHeight() {
    ScrollPane scrollPane = (ScrollPane) lookup(".scroll-pane");
    scrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
    scrollPane.setVbarPolicy(ScrollBarPolicy.NEVER);

    StackPane viewport = (StackPane) scrollPane.lookup(".viewport");

    Region content = (Region) viewport.lookup(".content");

    Text text = (Text) content.lookup(".text");
    text.textProperty().addListener(textHeightListener(text));
  }

  private InvalidationListener textHeightListener(Text text) {
    return (property) -> {
      // + 1 for little margin
      double textHeight = text.getBoundsInLocal().getHeight() + 1;

      //To prevent that our TextArena will be smaller than our TextField
      //I used DEFAULT_HEIGHT = 18.0
      if (textHeight < DEFAULT_HEIGHT) {
        textHeight = DEFAULT_HEIGHT;
      }

      setMinHeight(textHeight);
      setPrefHeight(textHeight);
      setMaxHeight(textHeight);
    };
  }
邹星火
2023-03-14

等待一个更好的,我使用这个黑客解决方案。

  • 查找文本区域的垂直滚动条。
  • 使其透明
  • 听它的可见属性
  • 当滚动条变得可见时,我将一行添加到文本区域。

代码:

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;
    }
}
魏晨
2023-03-14

问题;文本区域的高度希望在其文本通过用户键入或复制粘贴更改时增加或缩小。这是另一种方法:

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);
    }
}

但它有一个缺点;只有当多行之间有换行符(即Enter键)时,文本区域的高度才会改变,如果用户键入足够长的时间,文本将换行为多行,但高度不会改变。

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

textHolder.setWrappingWidth(textArea.getWidth() - 10);

primaryStage.show();之后。它适用于用户没有换行符的长打字。然而,这会产生另一个问题。当用户通过点击“退格”来删除文本时,就会出现这个问题。问题发生在更改文本持有人高度以及将文本区域的高度设置为新值的位置。我觉得这可能是一个错误,没有深入观察。

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

 类似资料:
  • 问题内容: 我有一个如下所示的div页面 样式 我想调整div的高度以填充(或拉伸到)整个div (标有绿色边框),并且不想越过页脚divD。我该如何解决? 问题答案: 只需添加到造型。应该没有必要。

  • 问题内容: 我需要伸展黄色的孩子来填补父母的所有身高。无需设置父级高度。父级的高度应取决于蓝色的子级文本。 问题答案: 使用Flexbox时,主要错误是开始全面使用。 在很多情况下,我们已经习惯了这一点,尽管谈到Flexbox时,它通常会破坏它。 解决方案很简单,只需删除,它将自动运行。 它的原因,是 柔性的项目 在 行 方向(默认),控制垂直行为,并作为其默认的是这只是工作原样。 堆栈片段

  • 问题内容: 我想为不同的div设置背景图像,但是我的问题是: 图片尺寸为固定值(60px)。 改变div的大小 如何拉伸背景图像以填充整个div背景? 问题答案: 加 到背景图片下方的CSS。 您还可以指定确切的尺寸,即:

  • 这是我当前gridview的图像: 这是我的griview布局: 这是我的自定义行: 我已经试了大约3个小时,但我不能,上面的代码是我的最新代码。你能帮我吗?如何使两行填充宽度? 谢谢

  • 我有一个容器div设置了宽度和高度,溢出设置为自动。在内部,有一个无序列表,其中包含导致div滚动的内容。 问题是列表本身没有扩展到容器div之外。所以当我尝试在列表的右侧添加填充时,它并不能正常工作: CSS 这里有一把小提琴说明了问题。

  • 我正在使用flexbox布局将三个div定位在一列中,以便每个div具有相同的高度。如果每个div的内容太大,则会显示滚动条。我希望每一节只扩展到其内容的高度,但目前发生的情况是,每一节总是相同的高度,而不管其中的内容如何。 如果容器是900px,则每个节应该是300px,如果一个节的内容超过300px高,则应该出现滚动条。但是,如果lets的内容说中间的部分只有100px高,那部分应该只有100