【问题标题】:Test for Label overrun测试标签溢出
【发布时间】:2013-07-11 09:45:04
【问题描述】:

我有一个多行标签,其文本可能会溢出。如果它这样做,我想减小字体大小,直到它没有溢出,或者直到它达到某个最小大小。这有望使标签改变大小,直到整个字符串可见。

我的问题是我不确定如何测试文本是否已溢出。我尝试测试标签的文本是否以椭圆字符串结尾,但我相信椭圆在技术上并未添加到标签的 textProperty 中。那么有人知道对此进行测试的好方法吗?

【问题讨论】:

标签: javafx-2 javafx


【解决方案1】:

简短而令人失望的答案:您根本无法以可靠的方式做到这一点。

略长一点的答案是,标签本身甚至不知道它是否溢出。每当调整标签大小时,皮肤类 (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());
  }
}

如果你使用这个皮肤为你的Label,你应该能够检测到你的文字是否是椭圆体。如果您想知道循环和反射:Java 不允许我通过其他方式访问文本字段,因此这可能是您真的不应该这样做的一个强有力的指标;-) 不过:它有效!

免责声明:我只检查了 JavaFX 8

【讨论】:

    【解决方案2】:

    minisu 在此答案中发布了一种检测溢出的方法: https://stackoverflow.com/a/15178908/9492864

    这种方式适用于所有标签,我在带有 JavaFX 8 的按钮上进行了测试。 例如,您可以将侦听器添加到 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);
    });
    

    【讨论】:

      【解决方案3】:

      这对我有用! 在 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);
            }
        }
      } 
      

      仅调用 asignarTexto(label, texto) 将文本设置为标签并检查标签中的文本是否超出范围,然后为标签添加工具提示。

      【讨论】:

        【解决方案4】:

        Johann 已经提到您可以使用(Text)labeled.lookup(".text") 获取标签的实际 显示文本,然后将其与预期 字符串进行比较...但是,就我而言,这不起作用。也许是因为我更新标签的频率很高,但实际的字符串总是比预期的少几个字符......

        所以,我选择使用setEllipsisString(String value) 方法将省略号字符串(溢出时附加到标签末尾的内容,默认为“...”)设置为(未使用) ASCII 控制字符,如 0x03(适当命名为“文本结尾”),然后每次设置标签文本后,我都会检查实际字符串的最后一个字符是否是控制字符。

        使用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
            }
        });
        

        请注意,您可以将控制字符设置为真正的任何字符,而不必只是一个字符;但是,如果您选择控制字符,check that it isn't commonly used

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-05-21
          • 1970-01-01
          • 2012-05-19
          • 2019-06-23
          • 1970-01-01
          • 2019-09-16
          • 2014-07-20
          • 2014-01-20
          相关资源
          最近更新 更多