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

如果溢出,调整JavaFX标签的大小,javafx,resize,label,ellipsis,overrun,Javafx,Resize,Label,Ellipsis,Overrun,我在标题窗格的网格窗格中有一个标签。如果超出范围,我希望它逐步缩小0.05em,这样三个点(“长标签…”)就不会以小字体显示->“长标签”。 标签的isOverrun()方法很好,但JavaFX没有提供,life也不是wishconcert。 到目前为止,我的工作是: Bounds tpBounds=tPane.getBoundsInLocal(); Bounds lblBounds=label.getBoundsInLocal(); 双字体大小=1.0; 而(tpBounds.getWidt

我在标题窗格的网格窗格中有一个标签。如果超出范围,我希望它逐步缩小0.05em,这样三个点(“长标签…”)就不会以小字体显示->“长标签”。

标签的isOverrun()方法很好,但JavaFX没有提供,life也不是wishconcert。
到目前为止,我的工作是:

Bounds tpBounds=tPane.getBoundsInLocal();
Bounds lblBounds=label.getBoundsInLocal();
双字体大小=1.0;
而(tpBounds.getWidth()0.5){
fontSize=fontSize-0.05;
label.setStyle(“-fx字体大小:“+fontSize+“em;”);
System.out.println(fontSize+“”+tpBounds.getWidth()+“”+lblBounds.getWidth());
}
问题是:在while循环期间,bounds.getWidth()始终显示原始宽度。使用新fontsize的“新”宽度刷新速度不够快,无法被while条件捕捉到,因此fontsize越来越低。
有什么解决方案吗?

编辑

我更常问:要使标签自身缩小,直到它适合而不截断,真的很难吗

解决方案:

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;
        }
    });
}
fontVerkleinerung(lblXYZ)//呼叫开始时调整大小
lblXYZ.styleProperty().addListener((可观察、旧版本、新版本)->{
fontVerkleinerung(lblXYZ);//如果调整了大小,请再次检查大小
}); 
私人void fontVerkleinerung(标签){
Platform.runLater(()->{
tpBounds=tPane.getBoundsInLocal();
if(label.getBoundsInLocal().getWidth()>tpBounds.getWidth()&&&!fontSizeFits){
fontSize=fontSize-0.02;
label.setStyle(“-fx字体大小:“+fontSize+“em;”);
}
if(label.getBoundsInLocal().getWidth()这是一个源自内部api的黑客攻击

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()
方法的逻辑并缩短计算时间。

另一种可行的方法是:

.setMinHeight(Region.USE_PREF_SIZE)

简单且比计算简单得多。

此函数发挥了神奇的作用,基本上计算当前标签宽度的计算大小首选宽度(可以根据标签的设置进行更改),如果较大,则将字体减少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);
}

同意命名对流的问题,可能是另一个问题,但这与文章无关???只需注意:Toolkit和FontLoader都不是公共api,因此不能在严格约束的上下文中使用。这些是我使用的库,很抱歉,在com.sun.javafx.tk.FontLoader com.sun.javafx.tk.Toolkit之前没有使用它
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);
}