2

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

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

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

实际与期望

**编辑**我在这个问题上取得了一些进展。我从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);

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

4

1 回答 1

1

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

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

包装盒

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

未夹紧的最大宽度

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 开发人员列表中的一些输入。也许一些额外的 api (如布尔包属性)会有条件地更新内部文本流布局算法以自动将文本流打包到最小大小,这将是一种更好的方法。部分困难在于,要以易于理解的方式编写问题是一个困难的问题。也很难说这是某种极端情况,还是更多人会遇到的情况(因此可能证明额外 API 的复杂性是合理的)。

于 2013-10-28T05:24:24.407 回答