问题
With Textflow.setMaxWidth(double)
I can achieve text wrapping.
But how can I adjust the width of TextFlow
afterwards so that it is based on the actual wrapping position?
In other words, how to let the TextFlow
bounds snap to all of its children Text
bounds to get rid of the empty space on the right:
**Edit** I have made some progress on this issue. My class derived from TextFlow
now contains:
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);
Unfortunately, this approach does not seem to be accurate yet, since it results in a second text flow change in some cases.
回答1:
The solution you posted in your question seemed to work OK for me on testing.
In the image below the scene has been resized to trigger wrapping of the TextFlow (shown in red). On the right, the TextFlow does not exactly wrap at the last visible character, because the last character in the line is a space, so the wrapping occurs after the space. Taking into account the TextFlow bounds are flush to all of the text as required.
If you unclamp the max width, you get the default behavior of the text box which is to have the width grow (as you can see below).
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);
}
}
The solution is a little bit of a hack, you might want to ask one of the JavaFX developers for some input on the openjfx developer list. Maybe some additional api like a boolean pack property which would conditionally update the internal textflow layout algorithm to automatically pack the textflow to a minimal size would be a way to do this better. Part of the difficulty is that it is a hard question to write in such a way that the issue is easily understandable. It is also hard to say if this is some kind of corner case or if it is something that more people will encounter (hence perhaps justifying the complexity of an additional API).
来源:https://stackoverflow.com/questions/19612591/javafx-optimal-width-of-textflow-with-word-wrap