简体   繁体   English

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

[英]How to calculate the pixel width of a String in JavaFX?

It appears that there is no API call to calculate the width (in pixels) of a text string in Java FX 2.2. 似乎没有API调用来计算Java FX 2.2中文本字符串的宽度(以像素为单位)。 There have been suggestions of workarounds on other forums, but my efforts to create or find any code that returns the width of a String, either using the default font or otherwise, have failed. 在其他论坛上已经提出了变通方法的建议,但是我使用默认字体或其他方式创建或查找返回String宽度的任何代码的尝试都失败了。 Any help would be appreciated. 任何帮助,将不胜感激。

If you are just measuring the default font without CSS: 如果您只是在没有CSS的情况下测量默认字体:

  1. Place the String to be measured in a Text object. 将要测量的字符串放在Text对象中。
  2. Get the width of the Text object's layout bounds. 获取Text对象的布局边界的宽度。

If you need to apply CSS: 如果您需要申请CSS:

  1. Place the String to be measured in a Text object. 将要测量的字符串放在Text对象中。
  2. Create a throwaway Scene and place the Text object in the Scene. 创建一次性场景并将Text对象放置在场景中。
  3. Take a snapshot of the Text (if you are using Java 7) or call applyCss for Java 8. 拍摄文本的快照(如果您使用的是Java 7)或调用applyCss for Java 8。
  4. Get the width of the Text object's layout bounds. 获取Text对象的布局边界的宽度。

This works because it forces a layout pass on the Text which calculates it's layout bounds. 这是有效的,因为它强制在Text上布局传递,计算它的布局边界。 The scene in step 2 is required because that is just the way the CSS processor works (it needs a node to be located in a Scene to be able to do its job). 步骤2中的场景是必需的,因为这只是CSS处理器的工作方式(它需要一个节点位于一个场景中才能完成它的工作)。 Definitely read the linked javadoc for applyCss if you want to understand the processing further. 如果您想进一步了解处理,请务必阅读applyCss的链接javadoc。

Sample Code 示例代码

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 (displays the width in pixels of an arbitrary piece of text): 示例程序输出(显示任意文本的宽度,以像素为单位):

示例程序输出

How (if at all) would this change if the text was printed to a graphicscontext with a set font? 如果将文本打印到带有设置字体的graphicscontext,如何(如果有的话)会发生变化?

Apply the font to a text object containing the same message you will plot to the canvas. 将字体应用于包含将绘制到画布的相同消息的文本对象。 Unlike when you are measuring text plotted to the scene graph, items plotted to a canvas do not have CSS applied to them, so you don't need to place the Text object in a scene and have CSS applied to it before measuring the text. 与测量绘制到场景图形的文本不同,绘制到画布的项目没有应用CSS,因此您无需将Text对象放置在场景中,并在测量文本之前将CSS应用于该场景。 You can measure the layout bounds of your text object and it will be the same as the bounds of the text plotted within the canvas with the same font. 您可以测量文本对象的布局边界,它将与使用相同字体在画布中绘制的文本边界相同。

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

This solution works up until java 8: 这个解决方案可以工作到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();

Those classes have since been removed and are not available in newer java version! 这些类已被删除,并且在较新的java版本中不可用!

I tried this: 我试过这个:

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

and it seems to be working fine. 它似乎工作正常。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM