我有一个多行标签,其文字有可能超限。如果它这样做,我想减小字体大小,直到它没有超越,或直到它达到一些最小尺寸。这有望使标签改变大小,直到整个字符串可见。
我的问题是我不知道如何测试以查看文本是否超限。我已经尝试过测试以查看标签的文本是否以椭圆字符串结尾,但我认为椭圆在技术上并未添加到标签的textProperty中。那么有谁知道测试这个的好方法?
答案 0 :(得分:4)
简短而令人失望的回答:你根本无法以可靠的方式做到这一点。
稍微长一点的答案是,标签本身甚至不知道它是否溢出。每当调整标签大小时,外观类(LabeledSkinBase
)负责更新显示的文本。但是,该类使用JavaFX utils类来计算椭圆体文本。这里的问题是,如果标签的尺寸需要,则相应的方法只返回椭圆体的字符串。皮肤本身永远不会被告知文本是否实际上是椭圆形的,它只是将显示的文本更新为返回的结果。
您可以尝试检查皮肤类的显示文本,但它受到保护。所以你需要做的是继承LabelSkin
,并实现类似的东西:
package com.sun.javafx.scene.control.skin;
import java.lang.reflect.Field;
import javafx.scene.control.Label;
@SuppressWarnings("restriction")
public class TestLabel extends LabelSkin {
private LabeledText labelledText;
public TestLabel(Label label) throws Exception {
super(label);
for (Field field : LabeledSkinBase.class.getDeclaredFields()) {
if (field.getName().equals("text")) {
field.setAccessible(true);
labelledText = (LabeledText) field.get(this);
break;
}
}
}
public boolean isEllipsoided() {
return labelledText != null && labelledText.getText() != null && !getSkinnable().getText().equals(labelledText.getText());
}
}
如果你使用这个皮肤标签,你应该能够检测你的文字是否是椭圆形的。如果你想知道循环和反射:Java不允许我通过其他方式访问文本字段,所以这可能是一个强烈的指示,你真的不应该这样做;-)尽管如此:它有效! / p>
免责声明:我只检查过JavaFX 8
答案 1 :(得分:1)
minisu发布了一种方法来检测此答案中的超限: https://stackoverflow.com/a/15178908/9492864
这种方式适用于所有标记的,我使用JavaFX 8在Buttons上测试它。 您可以将一个侦听器添加到needsLayoutProperty:
labeled.needsLayoutProperty().addListener((observable, oldValue, newValue) -> {
String originalString = labeled.getText();
Text textNode = (Text) labeled.lookup(".text"); // "text" is the style class of Text
String actualString = textNode.getText();
boolean clipped = !actualString.isEmpty() && !originalString.equals(actualString);
System.out.println("is " + originalString + " clipped: " + clipped);
});
答案 2 :(得分:0)
这对我有用!! 在javafx中
public class LabelHelper{
public static boolean necesitaTooltip(Font font, Label label){
Text text = new Text(label.getText());
text.setFont(font);
Bounds tb = text.getBoundsInLocal();
Rectangle stencil = new Rectangle(
tb.getMinX(), tb.getMinY(), tb.getWidth(), tb.getHeight()
);
Shape intersection = Shape.intersect(text, stencil);
Bounds ib = intersection.getBoundsInLocal();
return ib.getWidth() > label.getPrefWidth();
}
public static void asignarTexto(Label label, String texto){
label.setText(texto);
if (necesitaTooltip(label.getFont(), label)){
Tooltip tp = new Tooltip(texto);
label.setTooltip(tp);
}
}
}
仅将asetarTexto(label,texto)用作设置文本的标签,然后检查标签中的文本是否溢出,然后为标签添加工具提示。
答案 3 :(得分:0)
Johann已经提到您可以使用(Text)labeled.lookup(".text")
来获取标签的实际显示文本,然后将其与预期字符串进行比较。 ..但是,就我而言,这没有用。也许是因为我正在频繁更新Label,但是实际的String总是比预期的少几个字符。
因此,我选择使用setEllipsisString(String value)
方法将省略号字符串(溢出时附加在Label末尾,默认为“ ...”)设置为(未使用)
ASCII控制字符,例如0x03
(适当地命名为“文本结尾”),然后每次设置标签文本后,我都会检查实际String的最后一个字符是否为控制字符。
使用Platform.runLater(Runnable)
的示例:
import javafx.scene.control.Label;
import javafx.application.Platform;
import javafx.scene.text.Text;
...
Label label = new Label();
...
label.setEllipsisString("\003");
...
final String newText = "fef foo";
Platform.runLater(() -> {
label.setText(newText);
String actual = ((Text)label.lookup(".text")).getText();
// \003 is octal for the aforementioned "end of text" control char
if (actual.length() > 0 && actual.charAt(actual.length()-1) == '\003') {
// Handle text now that you know it's clipped
}
});
请注意,您可以将控件char设置为真正的任何字符,而不必只是一个char。但是,如果您选择控制字符check that it isn't commonly used。