如何在JavaFX中计算字符串的像素宽度?

2022-09-01 06:30:30

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


答案 1

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

  1. 将要测量的字符串放在 Text 对象中。
  2. 获取 Text 对象布局边界的宽度。

如果你需要应用 CSS:

  1. 将要测量的字符串放在 Text 对象中。
  2. 创建一次性场景并将 Text 对象放置在场景中。
  3. 拍摄文本的快照(如果您使用的是 Java 7)或调用适用于 Java 8 的 applyC。
  4. 获取 Text 对象布局边界的宽度。

这是有效的,因为它强制在文本上进行布局传递,以计算其布局边界。步骤 2 中的场景是必需的,因为这正是 CSS 处理器的工作方式(它需要一个节点才能位于场景中才能完成其工作)。如果你想进一步了解处理,一定要阅读应用程序Css的链接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

如果将文本打印到具有设置字体的图形上下文,这将如何(如果有的话)发生更改?

将字体应用于包含要打印到画布的相同消息的文本对象。与测量绘制到场景图的文本不同,绘制到画布上的项目没有应用 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);
    }
}

答案 2

我试过这个:

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

它似乎工作正常。


推荐