2

我在 TitledPane 的 GridPane 中有一个标签。如果超出范围,我希望它逐步缩小 0.05em,因此三个点(“Long Labe ...”)不会出现 - >“Long Label”很小。

标签的 isOverrun() 方法会很棒,但 JavaFX 不提供,生活也不是一场愿望音乐会。
所以到目前为止我的解决方法:

    Bounds tpBounds = tPane.getBoundsInLocal();
    Bounds lblBounds = label.getBoundsInLocal();
    Double fontSize = 1.0;

    while (tpBounds.getWidth() < lblBounds.getWidth() && fontSize > 0.5) {
        fontSize = fontSize-0.05;
        label.setStyle("-fx-font-size: "+fontSize+"em;");

        System.out.println(fontSize+" "+tpBounds.getWidth()+" "+lblBounds.getWidth());
    }

问题:在 while 循环期间,bounds.getWidth() 始终显示原始宽度。具有新字体大小的“新”宽度刷新速度不够快,无法被 while 条件捕获,因此字体大小越来越小。
任何解决方案?

编辑
我更常见的问题是:让标签本身缩小尺寸真的很难吗,直到它适合而不截断?!

4

4 回答 4

5

另一种有效的方法是:

.setMinHeight(Region.USE_PREF_SIZE)

比计算简单得多。

于 2017-03-04T20:58:18.300 回答
4

这是一个受内部 api 启发的 hack。

JavaFX 使用com.sun.javafx.scene.control.skin.Utils类来进行各种基于文本的计算。这还包括计算溢出文本到多少原始文本以及在哪里显示省略号文本等。

对于未包装和非多行标签文本,此类中仅使用了 3 种方法:

static String computeClippedText(Font font, String text, double width, OverrunStyle type, String ellipsisString)
static double computeTextWidth(Font font, String text, double wrappingWidth) {...}
static int computeTruncationIndex(Font font, String text, double width) {...}

由于这个类是一个内部 api,我只是将这 3 个方法(以及必要的类变量)复制到我自己的 Utils 类中并用作:

@Override
public void start( Stage primaryStage )
{
    final Label label = new Label( "Lorem Ipsum is simply dummy long text of the printing and typesetting industry" );
    label.setFont( Font.font( 10 ) );
    System.out.println( "originalText = " + label.getText() );

    Platform.runLater( () -> 
        {
            Double fontSize = label.getFont().getSize();
            String clippedText = Utils.computeClippedText( label.getFont(), label.getText(), label.getWidth(), label.getTextOverrun(), label.getEllipsisString() );
            Font newFont = label.getFont();

            while ( !label.getText().equals( clippedText ) && fontSize > 0.5 )
            {
                System.out.println( "fontSize = " + fontSize + ", clippedText = " + clippedText );
                fontSize = fontSize - 0.05;
                newFont = Font.font( label.getFont().getFamily(), fontSize );
                clippedText = Utils.computeClippedText( newFont, label.getText(), label.getWidth(), label.getTextOverrun(), label.getEllipsisString() );
            }

            label.setFont( newFont );
    } );

    Scene scene = new Scene( new VBox(label), 350, 200 );
    primaryStage.setScene( scene );
    primaryStage.show();
}

根据您的要求,您可以computeClippedText()进一步简化逻辑并提高方法的计算时间。

于 2016-01-28T15:28:58.953 回答
0

解决方案:

fontVerkleinerung(lblXYZ);   //call resizing at beginning


 lblXYZ.styleProperty().addListener((observable, oldV, newV) -> {
    fontVerkleinerung(lblXYZ);   //check size again if resized
 }); 


private void fontVerkleinerung(Label label) {
    Platform.runLater(() -> {
        tpBounds = tPane.getBoundsInLocal();
        if (label.getBoundsInLocal().getWidth()>tpBounds.getWidth() && !fontSizeFits) {
            fontSize = fontSize-0.02;
            label.setStyle("-fx-font-size: "+fontSize+"em;");
        }

        if (label.getBoundsInLocal().getWidth()<=tpBounds.getWidth() && !fontSizeFits) {
            fontSizeFits = true;
        }
    });
}

这种解决方法不是 100% 令人满意,由于 label.setStyle("..."); 上的图形更新速度缓慢,GUI 受到影响。
styleProperty-listener 启动需要几毫秒。
我尝试修复这个问题几个星期,总是找到一个可能的解决方案,但没有奏效。我希望有人能从这篇文章中获利。

于 2016-01-28T10:22:49.447 回答
-1

这个函数很神奇,基本上计算当前标签宽度的计算大小,preferedWidth(可能会根据标签的设置而改变),如果它更大,则将字体减少 0.5(也可以是自定义值)。

注意:考虑还设置一个条件,如果字体小于 0.5,以避免字体不达到 0。也可以用 while 而不是递归函数进行转换,也将是最佳的,我会同时设置以防万一

public Label ResizeTextIfOverrunRecursive(Label label, String text, double size) throws Exception {
    FontLoader fontLoader = Toolkit.getToolkit().getFontLoader();
    label.setFont(Font.font(size));
    double font = label.getFont().getSize();
    label.setStyle("-fx-font-size:" + (font) +"px;");
    label.applyCss();
    label.layout();
    label.setText(text);
    double prefWidth = label.getPrefWidth();
    if (fontLoader.computeStringWidth(label.getText(), label.getFont()) > prefWidth){
        return ResizeTextIfOverrunRecursive(label, text, size - 0.5);
    } else return label;
}

public void ResizeTextIfOverrunItaration(Label label, String text, double size) throws Exception {
    FontLoader fontLoader = Toolkit.getToolkit().getFontLoader();
    label.setFont(Font.font(size));
    double font = label.getFont().getSize();
    label.setStyle("-fx-font-size:" + (font) +"px;");
    label.applyCss();
    label.layout();
    double prefWidth = label.getPrefWidth();
    while (fontLoader.computeStringWidth(label.getText(), label.getFont()) > prefWidth){
        font -= 0.5;
        label.setStyle("-fx-font-size:" + (font) +"px;");
        label.applyCss();
        label.layout();
    }

    label.setText(text);
}
于 2019-08-19T07:04:29.690 回答