web-dev-qa-db-fra.com

Comment calculer la largeur en pixels d'une chaîne en JavaFX?

Il semble qu’aucun appel d’API ne permet de calculer la largeur (en pixels) d’une chaîne de texte dans Java FX 2.2. Il y a eu des suggestions de solutions de contournement sur d'autres forums, mais mes efforts pour créer ou trouver un code renvoyant la largeur d'une chaîne, en utilisant la police par défaut ou autrement, ont échoué. Toute aide serait appréciée.

23
Don Wills

Si vous ne mesurez que la police par défaut sans CSS:

  1. Placez la chaîne à mesurer dans un objet texte.
  2. Obtenir la largeur des limites de présentation de l'objet Texte.

Si vous avez besoin d'appliquer CSS:

  1. Placez la chaîne à mesurer dans un objet texte.
  2. Créez une scène jetable et placez l'objet Texte dans la scène.
  3. Prenez un instantané du texte (si vous utilisez Java 7) ou appelez applyCss pour Java 8.
  4. Obtenir la largeur des limites de présentation de l'objet Texte.

Cela fonctionne car il oblige le texte à être mis en page, ce qui calcule ses limites de mise en page . La scène de l'étape 2 est obligatoire car c'est la manière dont le processeur CSS fonctionne (il faut qu'un nœud soit situé dans une scène pour être capable de faire son travail). Lisez certainement le fichier javadoc lié pour applyCss si vous souhaitez comprendre davantage le traitement.

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

Exemple de sortie de programme (affiche la largeur en pixels d’un morceau de texte arbitraire):

Sample Program Output

Comment (le cas échéant) cela changerait-il si le texte était imprimé dans un contexte graphique avec une police définie? 

Appliquez la police à un objet texte contenant le même message que celui que vous allez tracer sur le canevas. Contrairement aux mesures de texte tracées sur le graphique de la scène, les éléments CSS associés à une zone de dessin ne sont pas traités par des CSS. Il n'est donc pas nécessaire de placer l'objet Texte dans une scène et de les appliquer avant de mesurer le texte. Vous pouvez mesurer les limites de la mise en page de votre objet texte et ce sera la même chose que les limites du texte tracé dans le canevas avec la même police.

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

Cette solution fonctionne jusqu'à 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();

Ces classes ont depuis été supprimées et ne sont plus disponibles dans la nouvelle version de Java!

16
Stas

J'ai essayé ceci:

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

et cela semble bien fonctionner.

9
Leonardo Santos
Bounds bounds = TextBuilder.create (). Text (text) .font (font) .build (). GetLayoutBounds (); 
 Double width = bounds.getWidth (); 
 Double height = bounds.getHeight () ;
1
dongfangshangren