TITLE:JLabelの文字列を折り返し
#navi(../)
RIGHT:Posted by [[aterai]] at 2004-03-02
*JLabelの文字列を折り返し [#o3086f99]
GlyphVectorを使って、ラベルの文字列を折り返して表示します。

-&jnlp;
-&jar;
-&zip;

//#screenshot
#ref(http://lh4.ggpht.com/_9Z4BYR88imo/TQTNbQw2SHI/AAAAAAAAAaw/AApL8KKml8E/s800/GlyphVector.png)

**サンプルコード [#b14ee862]
#code{{
private GlyphVector getWrappedGlyphVector(String str,
                                          float wrapping,
                                          Font font,
                                          FontRenderContext frc) {
  Point2D gmPos    = new Point2D.Double(0.0d, 0.0d);
  GlyphVector gv   = font.createGlyphVector(frc, str);
  float lineheight = (float) (gv.getLogicalBounds().getHeight());
  float xpos       = 0.0f;
  float advance    = 0.0f;
  int   lineCount  = 0;
  GlyphMetrics gm;
  for(int i=0;i<gv.getNumGlyphs();i++) {
    gm = gv.getGlyphMetrics(i);
    advance = gm.getAdvance();
    if(xpos<wrapping && wrapping<=xpos+advance) {
      lineCount++;
      xpos = 0.0f;
    }
    gmPos.setLocation(xpos, lineheight*lineCount);
    gv.setGlyphPosition(i, gmPos);
    xpos = xpos + advance;
  }
  return gv;
}
lbl2 = new JLabel() {
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D)g;
    if(isResized) {
      int wrap = lbl2.getWidth()
                 -lbl2.getInsets().left
                 -lbl2.getInsets().right;
      FontRenderContext frc = g2.getFontRenderContext();
      gvtext = getWrappedGlyphVector(str, wrap, lbl2.getFont(), frc);
      isResized = false;
    }
    g2.setPaint(Color.RED);
    g2.drawGlyphVector(gvtext,
                       lbl2.getInsets().left,
                       lbl2.getInsets().top+lbl2.getFont().getSize());
   }
};
lbl2.addComponentListener(new ComponentAdapter() {
  public void componentResized(ComponentEvent e) {
    isResized = true;
    lbl2.repaint();
  }
});
}}

**解説 [#uf9eb02f]
-上:JLabel
-中:GlyphVector
--ラベルのサイズが変更されるたびに GlyphVector を更新することで、文字列の折り返しを行っています。
-下:JTextArea
--JLabelのFont、背景色を設定した編集不可のJTextAreaをsetLineWrap(true);として、文字列の折り返しを行っています。

----
ラベルの幅ではなく、任意の場所で文字列を改行したい場合は、以下のようにhtmlタグを利用したり、編集不可にしたJTextPane、JTextAreaなどを使用します(参考:[[JTextPane、JLabelなどで複数行を表示>Swing/MultiLineLabel]])。

#code{{
label.setText("<html>文字列を適当なところで<br>折り返す。");
}}

**参考リンク [#yb614c32]
//-[http://java.sun.com/docs/books/tutorial/uiswing/14painting/concepts.html How Swing Components Are Displayed]
-[http://java.sun.com/docs/books/tutorial/uiswing/components/label.html How to Use Labels]
-[http://java.sun.com/javase/ja/6/docs/ja/api/java/awt/font/LineBreakMeasurer.html LineBreakMeasurer (Java Platform SE 6)]

**コメント [#ibb7abba]
- JTextArea#setLineWrap(true);を使う方法を追加、スクリーンショットの更新。 -- [[aterai]] &new{2009-01-05 (月) 17:15:36};

#comment