如果溢出,调整 JavaFX 标签大小
Posted
技术标签:
【中文标题】如果溢出,调整 JavaFX 标签大小【英文标题】:Resize JavaFX Label if overrun 【发布时间】:2016-05-02 22:30:50 【问题描述】:我在 TitledPane 的 GridPane 中有一个标签。如果超出范围,我希望它逐步缩小 0.05em,因此三个点(“Long Labe ...”)不会显示 -> “Long Label”小。 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 条件捕获,因此字体大小越来越低。有什么解决方案吗?编辑我更常问:让 Label 自己缩小尺寸,直到它适合而不截断真的有那么难吗?!
【问题讨论】:
【参考方案1】:另一种可行的方法是:
.setMinHeight(Region.USE_PREF_SIZE)
比计算简单得多。
【讨论】:
【参考方案2】:这是一个受内部 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()
方法的逻辑并提高计算时间。
【讨论】:
【参考方案3】:解决办法:
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 启动需要几毫秒的时间。 我尝试修复这个问题几个星期,总是找到一个可能的解决方案,但它没有工作。我希望有人能从这篇文章中获利。
【讨论】:
【参考方案4】:这个函数很神奇,基本上计算当前标签宽度的计算大小,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);
【讨论】:
同意命名对流的问题,可能是另一个,但这与帖子无关???? 请注意:Toolkit 和 FontLoader 都不是公共 api,因此不能在严格限制的上下文中使用 这些是我使用的库,抱歉在 com.sun.javafx.tk.FontLoader com.sun.javafx.tk.Toolkit 之前没有提及它以上是关于如果溢出,调整 JavaFX 标签大小的主要内容,如果未能解决你的问题,请参考以下文章
如何在 javafx 中调整 imageview 图像的大小?