Berechnen Sie die Anzeigebreite einer Zeichenfolge in Java


89

Wie berechnet man die Länge (in Pixel) eines Strings in Java?

Am besten ohne Swing.

BEARBEITEN: Ich möchte den String mit drawString () in Java2D zeichnen und die Länge für den Zeilenumbruch verwenden.


4
Ohne Schaukel? Welches Gerät benutzt du? Welche Schriftart? Welche Größe? Welcher Stil? All diese Dinge verändern die Anzeigebreite.
S.Lott

3
Wie wirst du die Schnur ziehen? Mit AWT? Oder mit einem anderen Toolkit? Die Größe der Zeichenfolge in Pixel hängt von der Zeichnungs-API ab, die das Pixel später zeichnet (und natürlich von der verwendeten Schriftart und der Schriftgröße und davon, ob die Schrift fett / kursiv ist usw.). Ohne Kenntnis der Zeichnungs-API und der Schrifteigenschaften hat eine Zeichenfolge keinerlei Größe.
Mecki

1
@S. Lott. Du hast es in einem. Ich war versucht, dies als Nicht-Frage zu schließen.
David Arno

1
@ David Arno: Ich bin ein Softie auf dem n00bz. Ich werde das [Anfänger] -Tag hinzufügen.
S.Lott

Für .NET-Äquivalente gibt es die TextRenderer-Klasse, siehe stackoverflow.com/questions/604298/…
Spoike

Antworten:


135

Wenn Sie nur AWT verwenden möchten, verwenden Sie Graphics.getFontMetrics(optional die Schriftart angeben , für eine nicht standardmäßige), um eine zu erhalten FontMetricsund dann FontMetrics.stringWidthdie Breite für die angegebene Zeichenfolge zu ermitteln.

Wenn Sie beispielsweise eine GraphicsVariable namens haben g, verwenden Sie:

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

Für andere Toolkits müssen Sie uns weitere Informationen geben - es wird immer Toolkit-abhängig sein.


7
Es ist möglicherweise klarer, wenn Sie eine Beispielverwendung angeben. Zunächst habe ich versucht, sie als statische Methode zu verwenden, da Sie sie so geschrieben haben.
Aequitas

Veraltet! aber immer noch die beste Methode! Warum lehnen sie eine Methode ab, wenn es keinen besseren Weg gibt !!! Ich verstehe es einfach nicht!
Iman

2
@Zich: Ich bin nicht sicher, welche Methode Sie sagen, ist veraltet - keine von ihnen ist in der Java 8-Dokumentation als veraltet markiert, soweit ich sehen kann ...
Jon Skeet

2
@Zich: Es ist eine Methode in Graphics, nicht FontMetrics. Aber Sie rufen an Toolkit.getFontMetrics, was in der Tat veraltet ist und worüber diese Methode nicht spricht ... Sie müssen bei solchen Dingen wirklich vorsichtig sein, insbesondere bevor Sie über das Melden von Fehlern sprechen ...
Jon Skeet

1
@Zich: Nun, ich würde nicht raten - ich würde die nicht veraltete Methode oder die nicht veralteten Methoden verwenden, die Toolkit.getFontMetricsstattdessen vorschlagen .
Jon Skeet

54

Es muss nicht immer vom Toolkit abhängig sein oder es muss nicht immer der FontMetrics-Ansatz verwendet werden, da zuerst ein Grafikobjekt abgerufen werden muss, das in einem Webcontainer oder in einer kopflosen Umgebung fehlt.

Ich habe dies in einem Web-Servlet getestet und es berechnet die Textbreite.

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

Fügen Sie diesen Dimensionen die erforderlichen Werte hinzu, um den erforderlichen Rand zu erstellen.


1
Ich denke nicht, dass das Erstellen einer affineTransform und eines fontRenderContext auf diese Weise zu einem guten Verhalten führt. Ich denke, font.getTransfrom () wäre logischer.
Lyth

1
Ihr Beispiel verwendet weiterhin die AWT-Funktionalität. Mit SWT Font zum Beispiel wird es nicht funktionieren, deshalb "wird es immer Toolkit-abhängig sein"
serg.nechaev

1
@Olofu Mark - getStringBounds gibt nur die logischen Grenzen an. Um es besser zu machen, sollte es getBounds () und LineMetrics verwenden, um die tatsächliche Höhe einschließlich Aufstieg + Abstieg abzurufen.
Jones

7

Verwenden Sie die Methode getWidth in der folgenden Klasse:

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

Und jetzt zu etwas ganz anderem. Das Folgende nimmt eine ariale Schriftart an und macht eine wilde Vermutung basierend auf einer linearen Interpolation von Zeichen gegen Breite.

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

Interessant, aber vielleicht nicht sehr praktisch.


1

Ich persönlich habe nach etwas gesucht, mit dem ich den mehrzeiligen Zeichenfolgenbereich berechnen kann, damit ich feststellen kann, ob der angegebene Bereich groß genug ist, um die Zeichenfolge zu drucken - unter Beibehaltung einer bestimmten Schriftart.

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;
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.