我在TitledPane的GridPane中有一个Label。如果它超限,我希望它逐步缩小0.05em,这样三个点(“Long Labe ......”)不会显示 - >小标签“长标签”。
一个isOverrun() - 标签的方法会很棒,但JavaFX不提供它,生活不是一个wishconcert。
所以我的工作到目前为止:
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()始终显示原始宽度。新的fontsize的“新”宽度不够快,不足以被while条件捕获,因此fontsize越来越低。
任何解决方案?
编辑
我更常问:是否真的很难让Label自身缩小尺寸,直到它适合而不截断?!
答案 0 :(得分:3)
这是一个受内部api启发的黑客攻击。
JavaFX使用Run 64, 0.379999995232
...
Run 100, 0.379999995232
类来进行各种基于文本的计算。这还包括计算超出文本到原始文本的剪辑量以及显示省略号文本的位置等。
对于未包装而非多线标签文本,此类中只使用了3种方法:
com.sun.javafx.scene.control.skin.Utils
由于这个类是内部api,我只是将这3个方法(连同必要的类变量)复制到我自己的Utils类中,并用作:
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) {...}
根据您的要求,您可以进一步简化逻辑并改善@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();
}
方法的计算时间。
答案 1 :(得分: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(&#34; ...&#34;)的图形更新速度慢,GUI正在受到影响。
这需要几秒钟的时间才能获得styleProperty-listener的支持。
我试图解决这个问题几个星期了,总是找到一个可能的解决方案,但它没有用。我希望有人能从这篇文章中获利。
答案 2 :(得分:0)
另一种有效的方法是:
.setMinHeight(Region.USE_PREF_SIZE)
比计算它简单易行。
答案 3 :(得分:-1)
这个函数神奇,基本上计算当前标签宽度的计算大小,preferredWidth(可以根据标签的设置而改变),如果更大,则减小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);
}