Resize JavaFX Label if overrun

后端 未结 4 1376
情深已故
情深已故 2020-12-11 11:28

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\" i

4条回答
  •  庸人自扰
    2020-12-11 11:42

    This is a hack inspired from internal api.

    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.

    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) {...}
    

    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();
    }
    

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

提交回复
热议问题