9

graphics2DJavaを使用して、オブジェクト上の長方形に限定されるようにテキストをレンダリングする組み込みの方法はありますか?

私は使用できることを知っていますGraphics2D.drawStringが、それはテキストのほんの一行を描くだけです。

使えることも知っています

FontMetrics fm= graphics.getFontMetrics(font);
Rectangle2D rect=fm.getStringBounds("Some Text",graphics);

Font fontあるオブジェクトでsomeを使用してレンダリングされたときに、文字列の境界に関する情報を取得しGraphics2D graphicsます。

そのため、ループを開始したり、文字列を壊したりして、長方形の中に収まるように強制することができました。

しかし、私はそれらを書く必要がないことをはるかに望んでいます...

これを行う既製の関数はありますか?

4

5 に答える 5

7

これはあなたが探しているものかもしれません:

StringUtils.java:

import java.awt.FontMetrics;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

/**
 * Globally available utility classes, mostly for string manipulation.
 * 
 * @author Jim Menard, <a href="mailto:jimm@io.com">jimm@io.com</a>
 */
public class StringUtils {
  /**
   * Returns an array of strings, one for each line in the string after it has
   * been wrapped to fit lines of <var>maxWidth</var>. Lines end with any of
   * cr, lf, or cr lf. A line ending at the end of the string will not output a
   * further, empty string.
   * <p>
   * This code assumes <var>str</var> is not <code>null</code>.
   * 
   * @param str
   *          the string to split
   * @param fm
   *          needed for string width calculations
   * @param maxWidth
   *          the max line width, in points
   * @return a non-empty list of strings
   */
  public static List wrap(String str, FontMetrics fm, int maxWidth) {
    List lines = splitIntoLines(str);
    if (lines.size() == 0)
      return lines;

    ArrayList strings = new ArrayList();
    for (Iterator iter = lines.iterator(); iter.hasNext();)
      wrapLineInto((String) iter.next(), strings, fm, maxWidth);
    return strings;
  }

  /**
   * Given a line of text and font metrics information, wrap the line and add
   * the new line(s) to <var>list</var>.
   * 
   * @param line
   *          a line of text
   * @param list
   *          an output list of strings
   * @param fm
   *          font metrics
   * @param maxWidth
   *          maximum width of the line(s)
   */
  public static void wrapLineInto(String line, List list, FontMetrics fm, int maxWidth) {
    int len = line.length();
    int width;
    while (len > 0 && (width = fm.stringWidth(line)) > maxWidth) {
      // Guess where to split the line. Look for the next space before
      // or after the guess.
      int guess = len * maxWidth / width;
      String before = line.substring(0, guess).trim();

      width = fm.stringWidth(before);
      int pos;
      if (width > maxWidth) // Too long
        pos = findBreakBefore(line, guess);
      else { // Too short or possibly just right
        pos = findBreakAfter(line, guess);
        if (pos != -1) { // Make sure this doesn't make us too long
          before = line.substring(0, pos).trim();
          if (fm.stringWidth(before) > maxWidth)
            pos = findBreakBefore(line, guess);
        }
      }
      if (pos == -1)
        pos = guess; // Split in the middle of the word

      list.add(line.substring(0, pos).trim());
      line = line.substring(pos).trim();
      len = line.length();
    }
    if (len > 0)
      list.add(line);
  }

  /**
   * Returns the index of the first whitespace character or '-' in <var>line</var>
   * that is at or before <var>start</var>. Returns -1 if no such character is
   * found.
   * 
   * @param line
   *          a string
   * @param start
   *          where to star looking
   */
  public static int findBreakBefore(String line, int start) {
    for (int i = start; i >= 0; --i) {
      char c = line.charAt(i);
      if (Character.isWhitespace(c) || c == '-')
        return i;
    }
    return -1;
  }

  /**
   * Returns the index of the first whitespace character or '-' in <var>line</var>
   * that is at or after <var>start</var>. Returns -1 if no such character is
   * found.
   * 
   * @param line
   *          a string
   * @param start
   *          where to star looking
   */
  public static int findBreakAfter(String line, int start) {
    int len = line.length();
    for (int i = start; i < len; ++i) {
      char c = line.charAt(i);
      if (Character.isWhitespace(c) || c == '-')
        return i;
    }
    return -1;
  }
  /**
   * Returns an array of strings, one for each line in the string. Lines end
   * with any of cr, lf, or cr lf. A line ending at the end of the string will
   * not output a further, empty string.
   * <p>
   * This code assumes <var>str</var> is not <code>null</code>.
   * 
   * @param str
   *          the string to split
   * @return a non-empty list of strings
   */
  public static List splitIntoLines(String str) {
    ArrayList strings = new ArrayList();

    int len = str.length();
    if (len == 0) {
      strings.add("");
      return strings;
    }

    int lineStart = 0;

    for (int i = 0; i < len; ++i) {
      char c = str.charAt(i);
      if (c == '\r') {
        int newlineLength = 1;
        if ((i + 1) < len && str.charAt(i + 1) == '\n')
          newlineLength = 2;
        strings.add(str.substring(lineStart, i));
        lineStart = i + newlineLength;
        if (newlineLength == 2) // skip \n next time through loop
          ++i;
      } else if (c == '\n') {
        strings.add(str.substring(lineStart, i));
        lineStart = i + 1;
      }
    }
    if (lineStart < len)
      strings.add(str.substring(lineStart));

    return strings;
  }

}

これを独自のクラスに入れて、持っていたものを使用するだけです。

FontMetrics fm= graphics.getFontMetrics(font);
Rectangle2D rect=fm.getStringBounds("Some Text",graphics);

あなたに応じてラップされたsのを返すwrap(String str, FontMetrics fm, int maxWidth)呼び出しは 、テキストの幅になります:ListStringmaxWidthRectangle2D

String text="Some Text";
FontMetrics fm= graphics.getFontMetrics(font);
Rectangle2D rect=fm.getStringBounds(text,graphics);
List<String> textList=StringUtils.wrap(text, fm, int maxWidth);

参照:

于 2012-08-26T11:28:38.493 に答える
7

私は助けることができる小さな関数を書きました。447は、テキストをレンダリングするために必要な幅から取得できる使用可能な幅です。

private void drawTextUgly(String text, FontMetrics textMetrics, Graphics2D g2)
{
    // Ugly code to wrap text
    int lineHeight = textMetrics.getHeight();
    String textToDraw = text;
    String[] arr = textToDraw.split(" ");
    int nIndex = 0;
    int startX = 319;
    int startY = 113;
    while ( nIndex < arr.length )
    {
        String line = arr[nIndex++];
        while ( ( nIndex < arr.length ) && (textMetrics.stringWidth(line + " " + arr[nIndex]) < 447) )
        {
            line = line + " " + arr[nIndex];
            nIndex++;
        }
        GraphicsUtility.drawString(g2, line, startX, startY);
        startY = startY + lineHeight;
    }
}
于 2012-11-19T06:10:58.240 に答える
4

この回答LabelRenderTestのソースを参照してください。HTML / CSSを使用し、CSSを使用して本文の幅を設定することで、行の折り返しを自動化します。

于 2012-08-26T11:32:39.273 に答える
2

一時的なJTextAreaを使用して、最大10行のコードで完全な行の折り返しを行います。

static void drawWrappedText(Graphics g, String text, int x, int y, int w, int h) {
    JTextArea ta = new JTextArea(text);
    ta.setLineWrap(true);
    ta.setWrapStyleWord(true);
    ta.setBounds(0, 0, w, h);
    ta.setForeground(g.getColor());
    ta.setFont(g.getFont());
    Graphics g2 = g.create(x, y, w, h); // Use new graphics to leave original graphics state unchanged
    ta.paint(g2);
}
于 2021-02-04T07:31:52.193 に答える
1
 private List<String> wrap(String txt, FontMetrics fm, int maxWidth){
    StringTokenizer st =  new  StringTokenizer(txt)  ;

    List<String> list = new ArrayList<String>();
    String line = "";
    String lineBeforeAppend = "";
    while (st.hasMoreTokens()){
       String seg = st.nextToken();
       lineBeforeAppend = line;
       line += seg + " ";
       int width = fm.stringWidth(line);
       if(width  < maxWidth){
           continue;
       }else { //new Line.
           list.add(lineBeforeAppend);
           line = seg + " ";
       }
    }
    //the remaining part.
    if(line.length() > 0){
        list.add(line);
    }
    return list;
}
于 2016-01-22T23:36:27.777 に答える