web-dev-qa-db-ja.com

JavaFXで文字列のピクセル幅を計算する方法は?

Java FX 2.2のテキスト文字列の幅(ピクセル単位)を計算するAPI呼び出しがないようです。他のフォーラムで回避策の提案がありましたが、デフォルトのフォントを使用しているかどうかに関係なく、文字列の幅を返すコードを見つけられなかった。

25
Don Wills

CSSなしでデフォルトのフォントを測定している場合:

  1. 測定する文字列をテキストオブジェクトに配置します。
  2. Textオブジェクトのレイアウト境界の幅を取得します。

CSSを適用する必要がある場合:

  1. 測定する文字列をテキストオブジェクトに配置します。
  2. 使い捨てシーンを作成し、Textオブジェクトをシーンに配置します。
  3. テキストのスナップショットを撮ります(Java 7を使用している場合)、またはJava 8.に対して applyCss を呼び出します)。
  4. 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

テキストが設定されたフォントでグラフィックスコンテキストに印刷された場合、(もしあれば)これはどのように変化しますか?

キャンバスにプロットするのと同じメッセージを含むテキストオブジェクトにフォントを適用します。シーングラフにプロットされたテキストを測定する場合とは異なり、キャンバスにプロットされたアイテムには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);
    }
}
36
jewelsea

このソリューションは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バージョンでは使用できません!

16
Stas

私はこれを試しました:

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

正常に動作しているようです。

12
Leonardo Santos
境界bounds = TextBuilder.create()。text(text).font(font).build()。getLayoutBounds(); 
 double width = bounds.getWidth(); 
 double height = bounds .getHeight();
1