Как сделать перенос слов на короткую строку с 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'sGraphics,

Другие вопросы по тегам