Javafx 2 如何拉伸TextArea以填充内容,并在此过程中展开父级?
因此,我有一个文本区域,当用户将段落粘贴到其中,或者只是在其中写入时,我希望它垂直扩展以显示所有可用的文本。也就是说,不要在文本字段本身中使用滚动条。。。就像许多网页上发生的事情一样。包括我在内的许多用户不喜欢被迫在一个小窗口中进行编辑。Facebook状态更新框的工作原理 我试过了Javafx 2 如何拉伸TextArea以填充内容,并在此过程中展开父级?,javafx-2,javafx-8,Javafx 2,Javafx 8,因此,我有一个文本区域,当用户将段落粘贴到其中,或者只是在其中写入时,我希望它垂直扩展以显示所有可用的文本。也就是说,不要在文本字段本身中使用滚动条。。。就像许多网页上发生的事情一样。包括我在内的许多用户不喜欢被迫在一个小窗口中进行编辑。Facebook状态更新框的工作原理 我试过了 myTextArea.autoSize() 裹着 myTextArea.textProperty().addListener(新的ChangeListener()…) 但这不起作用。我认为它很高兴自动调整到当前大
myTextArea.autoSize()
裹着
myTextArea.textProperty().addListener(新的ChangeListener()…)代码>
但这不起作用。我认为它很高兴自动调整到当前大小
左锚、右锚和顶锚都设置为其父锚平面。我试过了,底部连着,没有连着。理想情况下,我希望随着文本区域的增长而增长锚定窗格
我不介意阅读TextProperty并计算我自己设置的触发器大小。。。但是,如果已经有了最佳实践,那么这似乎是一种不成熟的方法。javafx的属性和子对象的数量足以让人望而生畏,因此在这里提出这个问题似乎是一个好问题,而不是试图找出字体/段落等占用了多少像素
更新:
所以我想也许我想得太多了,我所需要做的就是关掉滚动条,剩下的事情就会发生。唉,在寻找“滚动”、“垂直”、“vbar”的可用字段和方法时,我找不到可用的字段和方法。ScrollTopProperty看起来像是用于其他用途。在等待更好的解决方案时,我使用了这个黑客解决方案
- 查找文本区域的垂直滚动条
- 让它透明
- 倾听它的可见属性
- 当滚动条可见时,我会在文本区域中添加一行
守则:
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;
}
}
导入javafx.application.application;
导入javafx.beans.value.ChangeListener;
导入javafx.beans.value.observeValue;
导入javafx.collections.ObservableList;
导入javafx.geometry.Orientation;
导入javafx.scene.Node;
导入javafx.scene.Parent;
导入javafx.scene.scene;
导入javafx.scene.control.ScrollBar;
导入javafx.scene.control.TextArea;
导入javafx.scene.layout.ancorpane;
导入javafx.stage.stage;
公共类growtextarea扩展应用程序{
公共静态void main(字符串[]args){
发射(args);
}
@凌驾
public void start(Stage primaryStage)引发异常{
锚烷根=新锚烷();
root.setStyle(“-fx填充:20;-fx背景色:dodgerblue;”);
最终TextArea TextArea=新TextArea();
AnchorPane.setTopAnchor(文本区域,10.0);
AnchorPane.setLeftAnchor(文本区域,10.0);
AnchorPane.setRightAnchor(文本区域,10.0);
root.getChildren().add(textArea);
原始阶段。设置场景(新场景(根,400300));
primaryStage.show();
ScrollBar ScrollBar=lookupVerticalScrollBar(文本区域);
滚动条。设置不透明度(0.0);
scrollBar.visibleProperty().addListener(新的ChangeListener()){
@凌驾
public void已更改(ObservalEvalue此问题;当用户键入或复制粘贴文本时,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);
}
}
在primaryStage.show();
之后。它适用于用户不使用换行符的长时间打字。但是,这会产生另一个问题。当用户通过单击“backspace”删除文本时,会出现此问题。当textHolder高度发生更改,textArea的高度设置为新值时,问题就出现了。我认为这可能是一个错误,没有深入观察
在这两种情况下,复制粘贴都得到了正确的处理。我在创建扩展TextArea时遇到了类似的问题。我创建的TextArea看起来像TextField,每次行中没有更多空间时都会垂直扩展。
我已经在stack和其他可用的源代码中测试了所有关于这个主题的解决方案。我发现很少有好的解决方案,但都不够好
经过几个小时的战斗,我想出了这个办法
我扩展了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);
};
}
@覆盖
受保护的void layoutChildren(){
super.layoutChildren();
setWrapText(真);
addListenerToTextHeight();
}
私有void addListenerToTextHeight(){
滚动窗格滚动窗格=(滚动窗格)查找(“滚动窗格”);
scrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
scrollPane.setVbarPolicy(ScrollBarPolicy.NEVER);
StackPane viewport=(StackPane)scrollPane.lookup(“.viewport”);
区域内容=(区域)viewport.lookup(“.content”);
Text Text=(Text)content.lookup(“.Text”);
text.textProperty().addListener(textHeightListener(text));
}
私有无效侦听器文本高度侦听器(文本){
返回(属性)->{
//+1表示小余量
double textHeight=text.getBoundsInLocal().getHeight()+1;
//为了防止我们的TextArena比我们的TextField小
//我使用了默认的高度=18.0
如果(文本高度<默认高度){
text高度=默认高度;
}
设置最小高度(文本高度);
setPrefHeight(文本高度);
setMaxHeight(文本高度);
};
}
我使用了前面答案中的一些代码。
GrowthTextAreaIfRequired方法将增加textArea的高度,直到滚动条不可见为止(本例中限制为20行)
这种方法的问题是需要多次重新绘制窗口,直到找到理想的高度
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;
}
private void growTextAreaIfNecessary(TextArea textArea) {
Platform.runLater(() -> {
ScrollBar lookupVerticalScrollBar = lookupVerticalScrollBar(textArea);
int prefRowCount = textArea.getPrefRowCount();
if (lookupVerticalScrollBar.isVisible() && prefRowCount < 20) {
textArea.setPrefRowCount(prefRowCount + 1);
System.out.println("increasing height to: " + (prefRowCount + 1));
growTextAreaIfNecessary(textArea);
}
});
}
private ScrollBar lookupVerticalScrollBar(节点){
if(滚动条的节点实例&((滚动条)节点).getOrientation()==Orientation.VERTICAL){
返回(滚动条)节点;
}
if(父节点的节点实例){
可观察儿童=((Pa)
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;
}
private void growTextAreaIfNecessary(TextArea textArea) {
Platform.runLater(() -> {
ScrollBar lookupVerticalScrollBar = lookupVerticalScrollBar(textArea);
int prefRowCount = textArea.getPrefRowCount();
if (lookupVerticalScrollBar.isVisible() && prefRowCount < 20) {
textArea.setPrefRowCount(prefRowCount + 1);
System.out.println("increasing height to: " + (prefRowCount + 1));
growTextAreaIfNecessary(textArea);
}
});
}