JavaFX:带有自动换行的 TextFlow 的最佳宽度

标签 javafx word-wrap bounds javafx-8

使用 Textflow.setMaxWidth(double) 我可以实现文本换行。

但是之后如何调整 TextFlow 的宽度,使其基于实际的换行位置?

换句话说,如何让 TextFlow 边界捕捉到其所有子 Text 边界以摆脱右侧的空白区域:

actual vs. desired

**编辑** 我在这个问题上取得了一些进展。我的派生自 TextFlow 的类现在包含:

    double maxChildWidth = 0;
    for (Node child : getManagedChildren()) {
        double childWidth = child.getLayoutBounds().getWidth();
        maxChildWidth = Math.max(maxChildWidth, childWidth);
    }
    double insetWidth = getInsets().getLeft() + getInsets().getRight();
    double adjustedWidth = maxChildWidth + insetWidth;
    setMaxWidth(adjustedWidth);

不幸的是,这种方法似乎还不准确,因为在某些情况下它会导致第二次文本流更改。

最佳答案

您在问题中发布的解决方案在测试中似乎对我来说工作正常。

在下图中,场景已调整大小以触发 TextFlow 的换行(以红色显示)。在右边,TextFlow 并没有在最后一个可见字符处完全换行,因为行中的最后一个字符是空格,所以换行发生在空格之后。考虑到 TextFlow 边界会根据需要刷新到所有文本。

wrapped box

如果您松开最大宽度,您将获得文本框的默认行为,即宽度增加(如下所示)。

unclamped max width

import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.text.*;
import javafx.stage.Stage;

public class TextFlowWrapper extends Application {

  @Override
  public void start(Stage stage) {
    TextFlow textFlow = new TextFlow(
      new Text(
        "Box with long description that should be wrapped"
      )
    ) {
      @Override
      protected void layoutChildren() {
        super.layoutChildren();

        double maxChildWidth = 0;
        for (Node child : getManagedChildren()) {
          double childWidth = child.getLayoutBounds().getWidth();
          maxChildWidth = Math.max(maxChildWidth, childWidth);
        }
        double insetWidth = getInsets().getLeft() + getInsets().getRight();
        double adjustedWidth = maxChildWidth + insetWidth;

        setMaxWidth(adjustedWidth);
      }
    };

    textFlow.setStyle("-fx-background-color: red");
    textFlow.setMaxWidth(Control.USE_PREF_SIZE);
    textFlow.setMaxHeight(Control.USE_PREF_SIZE);

    Button unclamp = new Button("Unclamp max width");
    unclamp.setOnAction(e -> textFlow.setMaxWidth(Double.MAX_VALUE));

    StackPane wrappedText = new StackPane(textFlow);

    VBox vbox = new VBox(
        unclamp,
        wrappedText
    );
    VBox.setVgrow(wrappedText, Priority.ALWAYS);

    Scene scene = new Scene(
        vbox
    );

    stage.setScene(scene);
    stage.show();
  }

  public static void main(String[] args) {
    launch(args);
  }
}

该解决方案有点复杂,您可能想向其中一位 JavaFX 开发人员询问有关 openjfx developer list 的一些信息.也许一些额外的 api,如 bool 包属性,有条件地更新内部文本流布局算法以自动将文本流打包到最小大小,将是更好地做到这一点的方法。部分困难在于,很难以易于理解的方式编写问题。也很难说这是某种极端情况,还是更多人会遇到这种情况(因此可能证明额外 API 的复杂性是合理的)。

关于JavaFX:带有自动换行的 TextFlow 的最佳宽度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19612591/

相关文章:

java - JTextPane 换行行为

wpf - 防止文本框在 WPF 中水平扩展

android - 获取 View 的绘制边界/矩形

Java 索引越界异常

objective-c - Swift 语言中的 UITabBarController、UINavigationController 和 UIViewController 间距

java - 为什么程序运行时我的舞台没有反应? ( java 外汇)

java - 使用 GMapsFX 和 FXML 时如何初始化 Google map API key ?

CSS:如何在奇怪的情况下强制自动换行?

eclipse - 在 Docker 容器中的 Eclipse 中运行 JavaFX GUI 应用程序时出现 fatal error

javascript - JavaFX WebEngine JavaScript 上行调用