I want to display some formatted text using TextFlow. Previousely, I used a simple Label (with wrapText set to true) to display that text (unformatted), but want to make use of a Library that provides a List of Texts that I would like to display using a TextFlow.
My problem is that the text I want to display is larger than the available Area. Labels cut off the text when running out of space. This works great. Unfortunately TextFlow does not. When the text gets too long, it overflows the Region the TextFlow is in. Neighboring TextFlows then overlap each other. How can I mimic the behavior of the Label?
An MWE can be found here and below. I use a GridPane with two columns. Three TextFlows on the left, three Labels at the right. The displayed text is the same for all six elements. It produces this window:
As you can see, the text on the left (in the TextFlows) overlaps.
I tried, without success:
- Setting the maxWidth and maxHeight of the TextFlow to the available Area
- Creating a rectangle of appropriate size and setting it as a clip
JAVA:
package sample;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;
public class Main extends Application {
@FXML
private TextFlow textFlow0;
@FXML
private TextFlow textFlow1;
@FXML
private TextFlow textFlow2;
@FXML
private Label label0;
@FXML
private Label label1;
@FXML
private Label label2;
private String longText = "This is some really long text that should overflow the available Area. " +
"For TextFields, this is handeled by cropping the text to appropriate length and adding \"...\" at the end. " +
"No such option exists for TextFlows";
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Text Overflow");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
@FXML
private void initialize() {
textFlow0.getChildren().add(new Text(longText));
textFlow1.getChildren().add(new Text(longText));
textFlow2.getChildren().add(new Text(longText));
label0.setText(longText);
label1.setText(longText);
label2.setText(longText);
}
public static void main(String[] args) {
launch(args);
}
}
FXML:
<?import javafx.scene.control.Label?>
<GridPane fx:controller="sample.Main"
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
<TextFlow fx:id="textFlow0" GridPane.rowIndex = "0" GridPane.columnIndex="0" />
<Label fx:id="label0" GridPane.rowIndex = "0" wrapText="true" GridPane.columnIndex="1"/>
<TextFlow fx:id="textFlow1" GridPane.rowIndex = "1" GridPane.columnIndex="0" />
<Label fx:id="label1" GridPane.rowIndex = "1" wrapText="true" GridPane.columnIndex="1"/>
<TextFlow fx:id="textFlow2" GridPane.rowIndex = "2" GridPane.columnIndex="0" />
<Label fx:id="label2" GridPane.rowIndex = "2" wrapText="true" GridPane.columnIndex="1"/>
</GridPane>
Failed: attempt to use clip
package sample;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.FlowPane;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;
public class Main extends Application {
@FXML
private FlowPane flowPane;
@FXML
private TextFlow textFlow0;
@FXML
private TextFlow textFlow1;
@FXML
private TextFlow textFlow2;
@FXML
private Label label0;
@FXML
private Label label1;
@FXML
private Label label2;
private String longText = "This is some really long text that should overflow the available Area. " +
"For TextFields, this is handeled by cropping the text to appropriate length and adding \"...\" at the end. " +
"No such option exists for TextFlows";
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Text Overflow");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
@FXML
private void initialize() {
flowPane.setPrefWrapLength(Double.MAX_VALUE);
Rectangle rect = new Rectangle();
rect.widthProperty().bind(flowPane.widthProperty());
rect.heightProperty().bind(flowPane.heightProperty());
flowPane.setClip(rect);
textFlow0.getChildren().add(new Text(longText));
textFlow1.getChildren().add(new Text(longText));
textFlow2.getChildren().add(new Text(longText));
label0.setText(longText);
label1.setText(longText);
label2.setText(longText);
}
public static void main(String[] args) {
launch(args);
}
}
FXML file for clip attempt
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.text.TextFlow?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.FlowPane?>
<GridPane fx:controller="sample.Main"
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
<FlowPane fx:id="flowPane" GridPane.rowIndex = "0" GridPane.columnIndex="0">
<TextFlow fx:id="textFlow0" />
</FlowPane>
<Label fx:id="label0" GridPane.rowIndex = "0" wrapText="true" GridPane.columnIndex="1"/>
<TextFlow fx:id="textFlow1" GridPane.rowIndex = "1" GridPane.columnIndex="0" />
<Label fx:id="label1" GridPane.rowIndex = "1" wrapText="true" GridPane.columnIndex="1"/>
<TextFlow fx:id="textFlow2" GridPane.rowIndex = "2" GridPane.columnIndex="0" />
<Label fx:id="label2" GridPane.rowIndex = "2" wrapText="true" GridPane.columnIndex="1"/>
</GridPane>