如何计算JavaFX中String的像素宽度?

时间:2012-10-22 16:30:05

标签: java javafx-2 javafx

似乎没有API调用来计算Java FX 2.2中文本字符串的宽度(以像素为单位)。在其他论坛上已经提出了变通方法的建议,但是我使用默认字体或其他方式创建或查找返回String宽度的任何代码的尝试都失败了。任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:33)

如果您只是在没有CSS的情况下测量默认字体:

  1. 将要测量的字符串放在Text对象中。
  2. 获取Text对象布局边界的宽度。
  3. 如果您需要应用CSS:

    1. 将要测量的字符串放在Text对象中。
    2. 创建一次性场景并将Text对象放置在场景中。
    3. 拍摄文本的快照(如果您使用的是Java 7)或者为Java 8调用applyCss
    4. 获取Text对象布局边界的宽度。
    5. 这是有效的,因为它强制在Text上布局传递,计算它的布局边界。 步骤2中的场景是必需的,因为这只是CSS处理器的工作方式(它需要一个节点位于一个场景中才能完成它的工作)。如果你想进一步理解处理,一定要阅读applyCss的链接javadoc。

      示例代码

      import javafx.application.Application;
      import javafx.scene.Scene;
      import javafx.scene.control.*;
      import javafx.scene.text.Text;
      import javafx.stage.Stage;
      
      // displays the width in pixels of an arbitrary piece of text.
      public class MeasureText extends Application {
        public static void main(String[] args) { launch(args); }
        @Override public void start(Stage stage) throws Exception {
          final Text text = new Text("XYZZY");
          new Scene(new Group(text));
      
          // java 7 => 
          //    text.snapshot(null, null);
          // java 8 =>
          text.applyCss(); 
      
          final double width = text.getLayoutBounds().getWidth();
      
          stage.setScene(new Scene(new Label(Double.toString(width))));
          stage.show();
        }
      }
      

      示例程序输出(显示任意一段文本的宽度):

      Sample Program Output

        

      如果将文本打印到带有设置字体的graphicscontext,这会如何改变(如果有的话)?

      将字体应用于包含您将绘制到画布的相同消息的文本对象。与测量绘制到场景图形的文本不同,绘制到画布的项目没有应用CSS,因此您无需将Text对象放置在场景中,并在测量文本之前将CSS应用于该场景。您可以测量文本对象的布局边界,它将与使用相同字体在画布中绘制的文本边界相同。

      import javafx.application.Application;
      import javafx.scene.Scene;
      import javafx.scene.canvas.*;
      import javafx.scene.control.Label;
      import javafx.scene.layout.VBox;
      import javafx.scene.text.*;
      import javafx.stage.Stage;
      
      // displays the width in pixels of an arbitrary piece of text (which has been plotted on a canvas).
      public class MeasureText extends Application {
          @Override
          public void start(Stage stage) throws Exception {
              final String msg = "XYZZY";
              final Text text = new Text(msg);
              Font font = Font.font("Arial", 20);
              text.setFont(font);
      
              final double width = text.getLayoutBounds().getWidth();
      
              Canvas canvas = new Canvas(200, 50);
              GraphicsContext gc = canvas.getGraphicsContext2D();
              gc.setFont(font);
              gc.fillText(msg, 0, 40);
      
              stage.setScene(new Scene(
                      new VBox(new Label(Double.toString(width)), canvas))
              );
              stage.show();
          }
      
          public static void main(String[] args) {
              launch(args);
          }
      }
      

答案 1 :(得分:16)

这个解决方案一直工作到java 8:

float width = com.sun.javafx.tk.Toolkit.getToolkit().getFontLoader().computeStringWidth("", gc.getFont());
float height = com.sun.javafx.tk.Toolkit.getToolkit().getFontLoader().getFontMetrics(gc.getFont()).getLineHeight();

这些类已被删除,并且在较新的java版本中不可用!

答案 2 :(得分:10)

我试过了:

Text theText = new Text(theLabel.getText());
theText.setFont(theLabel.getFont());
double width = theText.getBoundsInLocal().getWidth();

似乎工作正常。

答案 3 :(得分:1)

Bounds bounds = TextBuilder.create().text(text).font(font).build().getLayoutBounds();
double width=bounds.getWidth();
double height=bounds.getHeight();