Cómo calcular el ancho de píxel de una cadena en JavaFX?

Parece que no hay una llamada API para calcular el ancho (en píxeles) de una cadena de texto en Java FX 2.2. Se han sugerido soluciones alternativas en otros foros, pero mis esfuerzos para crear o encontrar cualquier código que devuelva el ancho de una cadena, ya sea con la fuente predeterminada o de otro modo, han fallado. Cualquier ayuda sería apreciada.

Si solo está midiendo la fuente predeterminada sin CSS:

  1. Coloque la cadena a medir en un objeto de texto.
  2. Obtenga el ancho de los límites de diseño del objeto de texto.

Si necesita aplicar CSS:

  1. Coloque la cadena a medir en un objeto de texto.
  2. Crea una escena desechable y coloca el objeto Texto en la escena.
  3. Tome una instantánea del texto (si está utilizando Java 7) o llame a applyCss para Java 8.
  4. Obtenga el ancho de los límites de diseño del objeto de texto.

Esto funciona porque obliga a pasar un diseño en el texto que calcula sus límites de diseño. La escena en el paso 2 es necesaria porque así es como funciona el procesador CSS (necesita un nodo para ubicarse en una escena para poder hacer su trabajo). Definitivamente, lea el javadoc vinculado para applyCss si desea comprender mejor el procesamiento.

Código de muestra

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

Salida de progtwig de muestra (muestra el ancho en píxeles de una pieza de texto arbitraria):

Muestra de salida del programa

¿Cómo (si es que lo hace) cambiaría esto si el texto se imprimiera en un contexto gráfico con una fuente establecida?

Aplique la fuente a un objeto de texto que contenga el mismo mensaje que trazará en el canvas. A diferencia de cuando se mide texto trazado en el gráfico de escena, los elementos trazados en un canvas no tienen CSS aplicado a ellos, por lo que no es necesario colocar el objeto de texto en una escena y aplicar CSS antes de medir el texto. Puede medir los límites del diseño de su objeto de texto y será igual a los límites del texto trazado dentro del canvas con la misma fuente.

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

Esta solución funciona hasta 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(); 

Esas clases ya han sido eliminadas y no están disponibles en la versión más nueva de java.

Intenté esto:

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

y parece estar funcionando bien.

  Limites límites = TextBuilder.create (). Texto (texto) .font (fuente) .build (). GetLayoutBounds ();
 ancho doble = bounds.getWidth ();
 doble altura = bounds.getHeight ();