Jak obliczyć długość (w pikselach) łańcucha w Javie?
Najlepiej bez Swingu.
EDYCJA: Chciałbym narysować ciąg za pomocą drawString () w Java2D i użyć długości do zawijania tekstu.
java
string-length
eflles
źródło
źródło
Odpowiedzi:
Jeśli chcesz tylko użyć AWT, użyj
Graphics.getFontMetrics
(opcjonalnie określając czcionkę, dla czcionki innej niż domyślna), aby uzyskać a,FontMetrics
a następnieFontMetrics.stringWidth
znaleźć szerokość dla określonego ciągu.Na przykład, jeśli masz
Graphics
zmienną o nazwieg
, użyjesz:int width = g.getFontMetrics().stringWidth(text);
W przypadku innych zestawów narzędzi musisz podać nam więcej informacji - zawsze będzie to zależne od zestawu narzędzi.
źródło
Graphics
, nieFontMetrics
. Ale dzwoniszToolkit.getFontMetrics
, co jest rzeczywiście przestarzałe i nie jest to, o czym mówi ta metoda ... musisz bardzo uważać na tego typu rzeczy, szczególnie zanim zaczniesz mówić o zgłaszaniu błędów ...Toolkit.getFontMetrics
zamiast tego metody, która nie jest przestarzała, lub sugeruje metody, które nie są przestarzałe .Nie zawsze musi to być zależne od zestawu narzędzi lub nie zawsze trzeba używać podejścia FontMetrics, ponieważ wymaga najpierw uzyskania obiektu graficznego, którego nie ma w kontenerze internetowym lub w środowisku bezgłowym.
Przetestowałem to w serwlecie sieciowym i oblicza on szerokość tekstu.
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());
Dodaj niezbędne wartości do tych wymiarów, aby utworzyć wymagany margines.
źródło
Użyj metody getWidth w następującej klasie:
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(); } }
źródło
A teraz coś zupełnie innego. W poniższym przykładzie przyjęto czcionkę Arial i dokonano dzikiego przypuszczenia na podstawie liniowej interpolacji znaku w funkcji szerokości.
// 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; }
Ciekawe, ale może niezbyt praktyczne.
źródło
Osobiście szukałem czegoś, co pozwoliłoby mi obliczyć wielowierszowy obszar ciągu, aby móc określić, czy dany obszar jest wystarczająco duży, aby wydrukować ciąg - z zachowaniem określonej czcionki.
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; }
źródło