Как сделать перенос слов на короткую строку с TextLayout в Java Graphics2d?
Как бы вы эффективно применили перенос слов к короткой метке String ниже с TextLayout в Java?
Мой ярлык состоит всего из двух или трех слов. Некоторые примеры: 1. Надувная оранжерея D10; 2. Центр управления и контроля А5; 3. Джейсон Борис;
Я хотел бы обернуть слова таким образом, чтобы они имели форму квадрата, а не одного длинного прямоугольника.
Итак, мой вопрос: что нужно для переноса названий зданий во 2-ю строку вместо одной длинной строки? Смотрите картинку ниже:
Есть ли способ установить максимальное количество символов, которое должно содержаться в строке текста, и перенести оставшиеся символы во вторую строку и т. Д. (Необходимо учитывать пробелы)?
Например, я бы хотел обернуть название "Жилой квартал D12" в три строки.
Residential
Quarter
D12
и оберните "Командование и управление D16" в четыре строки.
Command
and
Control
D16
Разве не было бы хорошо, если бы TextLayout мог понимать HTML-коды, как обычный JLabel!? Тогда это будет легко:
String label = "<html>" + "Inflatable" + "<br>" + "Greenhouse" + "<br>" + "D10" + "</html>";
Примечание: это не должно быть одно слово в строке. Но я бы хотел, чтобы они были "центрированы" в каждой строке
У меня был следующий метод для генерации BufferedImage меток имени здания o или просто имени и фамилии человека.
private BufferedImage createLabelImage(
String label, Font font, FontRenderContext fontRenderContext, Color labelColor,
Color labelOutlineColor) {
// Determine bounds.
TextLayout textLayout1 = new TextLayout(label, font, fontRenderContext);
Rectangle2D bounds1 = textLayout1.getBounds();
// Get label shape.
Shape labelShape = textLayout1.getOutline(null);
// Create buffered image for label.
int width = (int) (bounds1.getWidth() + bounds1.getX()) + 4;
int height = (int) (bounds1.getHeight()) + 4;
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
// Get graphics context from buffered image.
Graphics2D g2d = (Graphics2D) bufferedImage.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.translate(2D - bounds1.getX(), 2D - bounds1.getY());
// Draw label outline.
Stroke saveStroke = g2d.getStroke();
g2d.setColor(labelOutlineColor);
g2d.setStroke(new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g2d.draw(labelShape);
g2d.setStroke(saveStroke);
// Fill label
g2d.setColor(labelColor);
g2d.fill(labelShape);
// Dispose of image graphics context.
g2d.dispose();
return bufferedImage;
}
Как видите, этот метод может создавать только форму метки BufferedImage только с одной строкой текста.
Поскольку я накладываю эти метки BufferedImage на карту, они выглядят слишком длинными и накладываются друг на друга.
Вот почему мне нужно, чтобы каждая этикетка имела форму квадрата, насколько это возможно.
1 ответ
Позвольте мне попытаться предложить алгоритм.
Разделите метку на пробел, чтобы получить список слов, и измерьте каждое слово, чтобы получить массив
int[] wordWidths;
int minWidth=max(wordWidths);
int height=the row height const;
int minHeight=height;
int maxHeight=wordWidths.length*height;
int currentWidth=minWidht;
int currentHeight=maxHeight;
while(currentWidth<currentHeight || wordWidths.length>1) {
int mergedWidth=find minimal sum of neighbour words' widths
replace the 2 widths with the mergedWidth reducing the wordWidthssize
currentHeight=wordWidths.length*height;
}
Или вы можете попробовать положиться на компоненты. Я бы определил JTextArea
например, назначив метку там и попытавшись поиграть с переносом, уменьшив ширину 1 на 1, и измерив предпочтительную высоту для ширины. Когда оптимальный размер достигнут, вы можете позвонить theWrappedJtextArea.printAll(g)
нарисовать это на вашем BufferedImage's
Graphics
,