如果溢出,调整 JavaFX 标签大小

人气:356 发布:2022-10-16 标签: label resize ellipsis javafx overrun

问题描述

我在 TitledPane 的 GridPane 中有一个标签.如果超出范围,我希望它逐步缩小 0.05em,这样三个点(Long Labe ...")就不会出现 -> Long Label"很小.标签的 isOverrun() 方法会很棒,但 JavaFX 不提供,生活也不是一场愿望音乐会.所以到目前为止我的解决方法:

I have a Label in a GridPane in a TitledPane. I want it to downsize stepwise by 0.05em if it is overrun so the three dots ("Long Labe...") dont show up -> "Long Label" in small. An isOverrun()-method for the Label would be great but JavaFX doesnt supply that and life isn't a wishconcert. So my workarround so far:

    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 条件捕获,因此字体大小越来越小.任何解决方案?编辑我更常见的问题是:让 Label 自己缩小尺寸,直到它适合而不截断真的有那么难吗?!

The problem: during the while loop, bounds.getWidth() is always showing the original width. The "new" width with the new fontsize is not refreshing quick enough to get catched by the while-condition, so the fontsize is getting lower and lower.Any Solutions?editI ask more commonly: Is it really THAT HARD to make a Label downsize itself, till it fits without truncating?!

推荐答案

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

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

The JavaFX uses com.sun.javafx.scene.control.skin.Utils class to various text based calculations. This also includes calculation of overrun texts to how much clip the original text and at where to show ellipsis text etc.

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

For the not wrapped and not multiline label texts there is only 3 methods used in this class:

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 类中并用作:

Since this class is an internal api, I just copied those 3 methods (along with necessary class variables) to my own Utils class and used as:

@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() 方法的逻辑并提高计算时间.

Based on your requirements you can simplify the logic and improve the calculation time of computeClippedText() method further.

179