Javaで文字列の表示幅を計算します


91

Javaで文字列の長さ(ピクセル単位)を計算する方法は?

Swingを使用しないことが望ましい。

編集:Java2DのdrawString()を使用して文字列を描画し、ワードラップに長さを使用したいと思います。


4
スイングなし?どのデバイスを使用していますか?どのフォント?大きさは?どんなスタイル?これらすべてが表示幅を変更します。
S.Lott 2008年

3
どのようにひもを描くつもりですか?AWTで?または他のツールキットを使用しますか?ピクセル単位の文字列のサイズは、後でピクセルを描画する描画APIによって異なります(もちろん、使用するフォント、フォントサイズ、フォントが太字/斜体かどうかなど)。描画APIとフォントのプロパティを知らなくても、文字列のサイズはまったくありません。
Mecki

1
@S。ロット。あなたはそれを一つにしています。私はこれを非質問として閉じたくなりました。
David Arno

1
@David Arno:私はn00bzのソフティです。[beginner]タグを追加します。
S.Lott 2008年

.NETと同等の場合はTextRendererクラスがあり、見るstackoverflow.com/questions/604298/...
Spoike

回答:


137

AWTを使用するだけの場合は、を使用してGraphics.getFontMetrics(デフォルト以外の場合は、オプションでフォントを指定します)、を取得してFontMetricsからFontMetrics.stringWidth、指定した文字列の幅を検索します。

たとえば、というGraphics変数がある場合はg、次を使用します。

int width = g.getFontMetrics().stringWidth(text);

他のツールキットについては、より多くの情報を提供する必要があります-それは常にツールキットに依存します。


8
使用例を提供すると、より明確になる可能性があります。最初は、そのように記述したので、静的メソッドとして使用しようとしました。
aequitas 2015

非推奨!しかし、それでも最良の方法です!、より良い方法がないのに、なぜ彼らは方法を非推奨にするのですか!!! わからない!
イマン

2
@Zich:私は確かにあなたは廃止されている方法を言っているのではないよ-これまで私が見ることができるようにされているJava 8のドキュメントで非推奨とどちらもそれらのマークされていません...
ジョンスキート

2
@Zich:これはのメソッドでありGraphics、ではありませんFontMetrics。しかし、あなたが呼んToolkit.getFontMetricsでいるのは、実際には非推奨であり、このメソッドが話していることではありません...特にバグの報告について話し始める前に、この種のことに本当に注意する必要があります...
Jon Skeet

1
@Zich:推測はしませんが、非推奨ではないメソッド、またはToolkit.getFontMetrics代わりに提案する非推奨ではないメソッドを使用します。
Jon Skeet 2017

55

ツールキットに依存する必要はありません。また、Webコンテナやヘッドレス環境に存在しないグラフィックオブジェクトを最初に取得する必要があるため、FontMetricsアプローチを使用する必要はありません。

これをWebサーブレットでテストしましたが、テキスト幅が計算されます。

import java.awt.Font;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;

...

String text = "Hello World";
AffineTransform affinetransform = new AffineTransform();     
FontRenderContext frc = new FontRenderContext(affinetransform,true,true);     
Font font = new Font("Tahoma", Font.PLAIN, 12);
int textwidth = (int)(font.getStringBounds(text, frc).getWidth());
int textheight = (int)(font.getStringBounds(text, frc).getHeight());

これらの寸法に必要な値を追加して、必要なマージンを作成します。


1
この方法でaffineTransformとfontRenderContextを作成しても、適切な動作が得られるとは思いません。font.getTransfrom()の方が論理的だと思います。
Lyth 2013年

1
あなたの例はまだAWT機能を使用しています。たとえば、SWTフォントでは機能しません。これが、「常にツールキットに依存する」
理由です

1
@Olofu Mark-getStringBoundsは、論理的な境界のみを示します。改善するには、getBounds()およびLineMetricsオブジェクトを使用して、ascent + descentを含む実際の高さを取得する必要があります。
ジョーンズ

8

次のクラスでgetWidthメソッドを使用します。

import java.awt.*;
import java.awt.geom.*;
import java.awt.font.*;

class StringMetrics {

  Font font;
  FontRenderContext context;

  public StringMetrics(Graphics2D g2) {

    font = g2.getFont();
    context = g2.getFontRenderContext();
  }

  Rectangle2D getBounds(String message) {

    return font.getStringBounds(message, context);
  }

  double getWidth(String message) {

    Rectangle2D bounds = getBounds(message);
    return bounds.getWidth();
  }

  double getHeight(String message) {

    Rectangle2D bounds = getBounds(message);
    return bounds.getHeight();
  }

}

1

そして今、完全に異なる何かのために。以下は、arialフォントを想定しており、文字と幅の線形補間に基づいてワイルドな推測を行います。

// Returns the size in PICA of the string, given space is 200 and 'W' is 1000.
// see https://p2p.wrox.com/access/32197-calculate-character-widths.html

static int picaSize(String s)
{
    // the following characters are sorted by width in Arial font
    String lookup = " .:,;'^`!|jl/\\i-()JfIt[]?{}sr*a\"ce_gFzLxkP+0123456789<=>~qvy$SbduEphonTBCXY#VRKZN%GUAHD@OQ&wmMW";
    int result = 0;
    for (int i = 0; i < s.length(); ++i)
    {
        int c = lookup.indexOf(s.charAt(i));
        result += (c < 0 ? 60 : c) * 7 + 200;
    }
    return result;
}

興味深いですが、おそらくあまり実用的ではありません。


1

私は個人的に、複数行の文字列領域を計算できるものを探していたので、特定のフォントを保持しながら、指定された領域が文字列を印刷するのに十分な大きさであるかどうかを判断できました。

private static Hashtable hash = new Hashtable();
private Font font;
private LineBreakMeasurer lineBreakMeasurer;
private int start, end;

public PixelLengthCheck(Font font) {
    this.font = font;
}

public boolean tryIfStringFits(String textToMeasure, Dimension areaToFit) {
    AttributedString attributedString = new AttributedString(textToMeasure, hash);
    attributedString.addAttribute(TextAttribute.FONT, font);
    AttributedCharacterIterator attributedCharacterIterator =
            attributedString.getIterator();
    start = attributedCharacterIterator.getBeginIndex();
    end = attributedCharacterIterator.getEndIndex();

    lineBreakMeasurer = new LineBreakMeasurer(attributedCharacterIterator,
            new FontRenderContext(null, false, false));

    float width = (float) areaToFit.width;
    float height = 0;
    lineBreakMeasurer.setPosition(start);

    while (lineBreakMeasurer.getPosition() < end) {
        TextLayout textLayout = lineBreakMeasurer.nextLayout(width);
        height += textLayout.getAscent();
        height += textLayout.getDescent() + textLayout.getLeading();
    }

    boolean res = height <= areaToFit.getHeight();

    return res;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.