在 JavaFX 中的特定行数之后截断文本
Truncating text after a specific number of lines in JavaFX
是否可以在 JavaFX 中截断固定行数后的标签或文本?对于 Web,有一个名为 'line-clamp' 的 CSS 属性。不幸的是,JavaFX 中似乎没有等效项。
对于标签,您可以选择将文本换行或使用显示的省略号将其截断。对于 Text 对象,至少可以指定包装方式。
未换行且未截断:
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eir mod tempor invidunt ut labore et dolore magna aliquyam
换行且未截断:
Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
sed diam nonumy eirmod tempor invidunt ut labore et dolore
magna aliquyam
未换行和截断:
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, ...
在 2 行后换行并截断(期望的行为):
Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
sed diam nonumy eirmod tempor invidunt ut labore et dolore ...
我提出了相当基本的解决方案(可以进一步改进)。
public class MultiLineLabel extends VBox {
private final String text;
private final List<Label> lines = new ArrayList<>();
public MultiLineLabel(String text, int maxNumberOfLines) {
if (maxNumberOfLines < 1) {
throw new IllegalArgumentException();
}
this.text = text;
// Create num. of lines labels
for (int i=0; i<maxNumberOfLines; i++) {
final Label label = new Label();
lines.add(label);
label.setTextOverrun(OverrunStyle.CLIP);
}
getChildren().addAll(lines);
}
@Override
protected void layoutChildren() {
super.layoutChildren();
String remainingText = this.text;
for (Iterator<Label> iterator = lines.iterator(); iterator.hasNext(); ) {
final Label currentLine = iterator.next();
// If this is the last line, just set the text and finish
if (!iterator.hasNext()) {
currentLine.setText(remainingText);
currentLine.setTextOverrun(OverrunStyle.ELLIPSIS);
break;
} else {
final String textThatFitsInThisLine = Utils.computeClippedText(currentLine.getFont(), remainingText, this.getWidth(), OverrunStyle.CLIP, null);
currentLine.setText(textThatFitsInThisLine);
remainingText = remainingText.substring(textThatFitsInThisLine.length());
}
}
}
}
... 然后可以像这样使用:
public class MultiLineLabelSSCCE extends Application {
@Override
public void start(Stage stage) {
final MultiLineLabel multiLineLabel =
new MultiLineLabel("This is some interesting text. The question is whether it's truncated properly. Let's see.", 3);
stage.setScene(new Scene(multiLineLabel));
stage.show();
}
}
演示(上述解决方案):
我希望这足以满足您的需要。
旁注:
此解决方案基于 com.sun.javafx.scene.control.skin.Utils
,它被视为实现细节,不是 JavaFx API 的一部分。要 运行 使用此解决方案的代码,您可能需要添加:
--add-exports=javafx.controls/com.sun.javafx.scene.control.skin=org.example
到您的运行配置(虚拟机选项)
是否可以在 JavaFX 中截断固定行数后的标签或文本?对于 Web,有一个名为 'line-clamp' 的 CSS 属性。不幸的是,JavaFX 中似乎没有等效项。
对于标签,您可以选择将文本换行或使用显示的省略号将其截断。对于 Text 对象,至少可以指定包装方式。
未换行且未截断:
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eir mod tempor invidunt ut labore et dolore magna aliquyam
换行且未截断:
Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
sed diam nonumy eirmod tempor invidunt ut labore et dolore
magna aliquyam
未换行和截断:
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, ...
在 2 行后换行并截断(期望的行为):
Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
sed diam nonumy eirmod tempor invidunt ut labore et dolore ...
我提出了相当基本的解决方案(可以进一步改进)。
public class MultiLineLabel extends VBox {
private final String text;
private final List<Label> lines = new ArrayList<>();
public MultiLineLabel(String text, int maxNumberOfLines) {
if (maxNumberOfLines < 1) {
throw new IllegalArgumentException();
}
this.text = text;
// Create num. of lines labels
for (int i=0; i<maxNumberOfLines; i++) {
final Label label = new Label();
lines.add(label);
label.setTextOverrun(OverrunStyle.CLIP);
}
getChildren().addAll(lines);
}
@Override
protected void layoutChildren() {
super.layoutChildren();
String remainingText = this.text;
for (Iterator<Label> iterator = lines.iterator(); iterator.hasNext(); ) {
final Label currentLine = iterator.next();
// If this is the last line, just set the text and finish
if (!iterator.hasNext()) {
currentLine.setText(remainingText);
currentLine.setTextOverrun(OverrunStyle.ELLIPSIS);
break;
} else {
final String textThatFitsInThisLine = Utils.computeClippedText(currentLine.getFont(), remainingText, this.getWidth(), OverrunStyle.CLIP, null);
currentLine.setText(textThatFitsInThisLine);
remainingText = remainingText.substring(textThatFitsInThisLine.length());
}
}
}
}
... 然后可以像这样使用:
public class MultiLineLabelSSCCE extends Application {
@Override
public void start(Stage stage) {
final MultiLineLabel multiLineLabel =
new MultiLineLabel("This is some interesting text. The question is whether it's truncated properly. Let's see.", 3);
stage.setScene(new Scene(multiLineLabel));
stage.show();
}
}
演示(上述解决方案):
我希望这足以满足您的需要。
旁注:
此解决方案基于 com.sun.javafx.scene.control.skin.Utils
,它被视为实现细节,不是 JavaFx API 的一部分。要 运行 使用此解决方案的代码,您可能需要添加:
--add-exports=javafx.controls/com.sun.javafx.scene.control.skin=org.example
到您的运行配置(虚拟机选项)