如何让JavaFX TextFlow实现长文本自动截断与溢出省略效果?
如何让JavaFX的TextFlow实现与Label一致的文本截断行为
我需要使用TextFlow展示格式化文本,此前我使用开启了wrapText属性的Label展示无格式文本,运行效果良好;现在我需要对接一款第三方库,该库会返回Text对象列表,我希望通过TextFlow来渲染这些内容。
我遇到的问题是:待展示文本长度超过可用区域大小时,Label会自动截断超出部分的文本,该机制运行稳定,但TextFlow无此特性,文本过长时会溢出自身所在的Region区域,导致相邻的TextFlow组件内容重叠。请问我该如何让TextFlow实现和Label一致的文本截断行为?
我使用了两列布局的GridPane做最小复现示例,左侧放置3个TextFlow,右侧放置3个Label,6个组件展示的文本内容完全一致。运行后生成的窗口如下:
可以看到左侧TextFlow内的文本出现了重叠。
我已尝试以下方案,均未生效:
- 将TextFlow的maxWidth和maxHeight设置为可用区域大小
- 创建适配尺寸的矩形对象,设置为TextFlow的裁剪(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>
裁剪方案尝试代码
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.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代码
<?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>
内容的提问来源于stack exchange,提问作者BenT
相关产品推荐
相关产品推荐

