【发布时间】:2021-07-26 09:38:43
【问题描述】:
我想使用 TextFlow 显示一些格式化文本。以前,我使用一个简单的标签(将 wrapText 设置为 true)来显示该文本(未格式化),但我想使用一个库来提供我想使用 TextFlow 显示的文本列表。
我的问题是我要显示的文本大于可用区域。当空间不足时,标签会切断文本。这很好用。不幸的是,TextFlow 没有。当文本变得太长时,它会溢出 TextFlow 所在的区域。相邻的 TextFlows 然后相互重叠。如何模仿标签的行为?
可以在here 及以下找到 MWE。 我使用带有两列的 GridPane。左边三个 TextFlow,右边三个 Label。所有六个元素的显示文本都是相同的。 它产生这个窗口:
如您所见,左侧的文本(在 TextFlows 中)重叠。
我试过了,没有成功:
- 将 TextFlow 的 maxWidth 和 maxHeight 设置为可用区域
- 创建一个适当大小的矩形并将其设置为剪辑
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>
失败:尝试使用剪辑
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>
【问题讨论】:
-
剪辑是最简单的解决方案,因为它可以防止文本溢出,至少在视觉上是这样。但是,
Text不提供在文本太长时自动回退到椭圆的方法。这种行为是由Labeled及其子类专门实现的。 -
我尝试过剪辑(如stackoverflow.com/questions/59705403/…),但没有成功。我会将它集成到 MWE 中并再次检查。
-
给你!感谢您的帮助!
-
一个提示,即使是一个最小的例子,从不让一个应用程序类也成为一个控制器类。您的应用程序应该只有一个应用程序实例。当应用程序也是控制器时,会在加载 fxml 时创建新实例,这通常意味着可能会出现微妙且难以调试的问题。此外,这违反了single responsibility principle。
-
我不建议尝试使用 GridPane 或 FlowPane 来解决这个问题,它们是更复杂的布局控件(我尝试过但未能快速完成)。将节点(仅 TextFlow 节点,不要混入标签)放在像 VBox 这样更简单的布局管理器中,然后尝试用它来解决问题。获取省略号逻辑可能会非常困难,因此我不建议尝试这样做,只需尝试剪裁溢出即可,即使这样也可能很棘手。