【问题标题】:Truncating text after a specific number of lines in JavaFX在 JavaFX 中特定行数后截断文本
【发布时间】:2021-01-14 08:26:06
【问题描述】:

是否可以在 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 ...

【问题讨论】:

  • 不,core fx 不支持这 - 第三方扩展可能(也许是 controlsfx,但没有检查)
  • @kleopatra 这就是我的想法。 ControlsFX 在他们的库中没有这样的东西。
  • 可能是RichTextFX?不确定它是否支持。
  • @James_D 好像不是这样。
  • 我不确定第三方库能否实现您想要的功能,至少在不侵入 JavaFX 内部的情况下无法实现。我发现 JavaFX 在私有代码中隐藏了很多关于文本和字体的有用信息。这是假设私有 API 一开始就可以做你想做的事。

标签: java javafx word-wrap


【解决方案1】:

我提出了相当基本的解决方案(可以进一步改进)。

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 到您的运行配置(VM 选项)

【讨论】:

  • 稍微调整一下:在方法结束时调用super.layoutChildren() 以避免省略号的闪烁。但无论如何,这是一个可行的解决方案。谢谢。
猜你喜欢
  • 1970-01-01
  • 2013-12-12
  • 2019-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-19
相关资源
最近更新 更多