Java에서 문자열의 표시 너비 계산


91

Java에서 문자열의 길이 (픽셀)를 계산하는 방법은 무엇입니까?

Swing을 사용하지 않는 것이 좋습니다.

편집 : Java2D에서 drawString ()을 사용하여 문자열을 그리고 단어 줄 바꿈에 길이를 사용하고 싶습니다.


4
스윙없이? 어떤 장치를 사용하고 있습니까? 무슨 글꼴? 어떤 크기? 어떤 스타일? 이 모든 것들이 디스플레이 너비를 변경합니다.
S.Lott

3
현을 어떻게 그릴 건가요? AWT로? 아니면 다른 툴킷으로? 픽셀 단위의 문자열 크기는 나중에 픽셀을 그릴 드로잉 API에 따라 다릅니다 (물론 어떤 글꼴을 사용하고 어떤 글꼴 크기와 글꼴이 굵게 / 기울임 꼴인지 등). 그리기 API와 글꼴 속성을 알지 못하면 문자열의 크기가 전혀 없습니다.
Mecki

1
@에스. Lott. 하나에 있습니다. 나는 이것을 질문이 아닌 것으로 끝내고 싶었습니다.
David Arno

1
@David Arno : 나는 n00bz의 약자입니다. [초보자] 태그를 추가하겠습니다.
S.Lott

.NET에 해당하는 TextRenderer 클래스가 있습니다. stackoverflow.com/questions/604298/…
Spoike

답변:


137

AWT를 사용하려면 Graphics.getFontMetrics(기본이 아닌 글꼴에 대해 선택적으로 글꼴 지정)을 사용하여 a FontMetrics를 가져온 다음 FontMetrics.stringWidth지정된 문자열의 너비를 찾습니다.

예를 들어라는 Graphics변수 가있는 경우 다음을 g사용합니다.

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

다른 툴킷의 경우 더 많은 정보를 제공해야합니다. 항상 툴킷에 따라 다릅니다.


8
예제 사용을 제공하면 더 명확 할 수 있습니다. 처음에는 그렇게 작성 했으므로 처음에는 정적 메서드로 사용하려고 시도했습니다.
Aequitas 2015-07-15

더 이상 사용되지 않습니다! 하지만 여전히 최선의 방법!, 더 나은 방법이 없을 때 왜 그들은 방법을 비난합니까 !!! 나는 그것을 이해하지 못한다!
Iman

2
@Zich : 나는 확실히 당신은 더 이상 사용되지 않는 방법을 말하고있는 게 아니에요 - 멀리 볼 수있는 것처럼 자바 8 문서에서 사용되지 않는로 둘 중 표시되지 않습니다 ...
존 소총

2
@Zich : 그것은의 방법이다 Graphics,하지 FontMetrics. 그러나 당신은를 호출 Toolkit.getFontMetrics하고 있는데, 이것은 정말로 더 이상 사용되지 않으며,이 메소드가 말하는 것과는 다릅니다 ... 특히 버그보고에 대해 이야기하기 전에 이런 종류의 것에 대해 정말로 조심해야합니다 ...
Jon Skeet

1
@Zich : 글쎄요, 저는 추측하지 않을 것입니다. 비추천 방법이나 Toolkit.getFontMetrics대신 제안하는 비추천 방법을 사용하겠습니다 .
Jon Skeet

55

웹 컨테이너 나 헤드리스 환경에없는 그래픽 객체를 먼저 가져와야하기 때문에 항상 툴킷에 의존 할 필요는 없거나 FontMetrics 접근 방식을 사용할 필요가 없습니다.

나는 이것을 웹 서블릿에서 테스트했으며 텍스트 너비를 계산합니다.

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

1
귀하의 예제는 여전히 AWT 기능을 사용하고 있습니다. SWT 글꼴로, 예를 들어, 일하지 않을이 왜 "항상 툴킷에 의존 될 것"입니다
serg.nechaev

1
@Olofu Mark-getStringBounds는 논리적 경계 만 제공합니다. 더 좋게 만들려면 getBounds () 및 LineMetrics 객체를 사용하여 상승 + 하강을 포함한 실제 높이를 검색해야합니다.
Jones

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.