Як обчислити довжину (у пікселях) рядка в Java?
Переважно без використання Swing.
EDIT: Я хотів би намалювати рядок за допомогою drawString () у Java2D і використовувати довжину для переносу слів.
Як обчислити довжину (у пікселях) рядка в Java?
Переважно без використання Swing.
EDIT: Я хотів би намалювати рядок за допомогою drawString () у Java2D і використовувати довжину для переносу слів.
Відповіді:
Якщо ви просто хочете використовувати AWT, тоді скористайтеся Graphics.getFontMetrics
(необов’язково вказавши шрифт, для шрифту, який не за замовчуванням), щоб отримати, FontMetrics
а потім FontMetrics.stringWidth
знайти ширину для вказаного рядка.
Наприклад, якщо у вас є Graphics
викликана змінна g
, ви б використали:
int width = g.getFontMetrics().stringWidth(text);
Що стосується інших наборів інструментів, вам потрібно буде надати нам більше інформації - вона завжди буде залежати від набору інструментів.
Graphics
, а не FontMetrics
. Але ви дзвоните Toolkit.getFontMetrics
, що насправді застаріло, і не про що говорить цей метод ... вам потрібно бути дуже обережними щодо такого роду речей, особливо перед тим, як почати говорити про повідомлення про помилки ...
Toolkit.getFontMetrics
замість цього застарілий метод або не застарілі методи .
Це не завжди повинно залежати від інструментарію, або не завжди потрібно використовувати підхід 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());
Додайте необхідні значення до цих розмірів, щоб створити будь-яке необхідне поле.
Використовуйте метод 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();
}
}
А тепер щось зовсім інше. Далі передбачається аріальний шрифт і робиться дика здогадка на основі лінійної інтерполяції символу проти ширини.
// 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;
}
Цікаво, але, можливо, не дуже практично.
Я особисто шукав щось, що дозволило б мені обчислити багаторядкову область рядка, щоб я міг визначити, чи є дана область достатньо великою для друку рядка - із збереженням конкретного шрифту.
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;
}