Swing/GlyphVector のバックアップソース(No.28)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- バックアップ を表示
- Swing/GlyphVector へ行く。
- 1 (2005-12-08 (木) 15:47:30)
- 2 (2006-02-27 (月) 15:58:14)
- 3 (2006-06-12 (月) 18:15:43)
- 4 (2006-06-22 (木) 17:31:50)
- 5 (2007-03-26 (月) 00:33:06)
- 6 (2007-04-07 (土) 15:37:38)
- 7 (2007-08-01 (水) 17:02:00)
- 8 (2007-08-16 (木) 17:24:50)
- 9 (2009-01-05 (月) 17:13:20)
- 10 (2009-08-07 (金) 20:19:03)
- 11 (2010-12-15 (水) 11:27:38)
- 12 (2011-03-18 (金) 19:10:33)
- 13 (2012-06-26 (火) 20:39:46)
- 14 (2013-01-01 (火) 20:54:53)
- 15 (2013-01-01 (火) 22:38:47)
- 16 (2013-02-20 (水) 15:35:30)
- 17 (2013-04-05 (金) 17:53:21)
- 18 (2013-08-20 (火) 14:38:05)
- 19 (2013-10-09 (水) 18:51:48)
- 20 (2013-11-12 (火) 16:50:09)
- 21 (2014-11-22 (土) 03:59:58)
- 22 (2014-11-25 (火) 03:03:31)
- 23 (2014-12-14 (日) 14:33:10)
- 24 (2015-03-18 (水) 18:48:56)
- 25 (2016-05-26 (木) 14:55:17)
- 26 (2016-06-02 (木) 12:27:14)
- 27 (2016-09-14 (水) 18:09:51)
- 28 (2017-03-29 (水) 16:14:28)
- 29 (2017-05-01 (月) 21:40:57)
- 30 (2018-04-25 (水) 18:56:12)
- 31 (2020-04-19 (日) 16:42:09)
- 32 (2021-10-21 (木) 19:06:59)
- 33 (2022-08-20 (土) 22:15:25)
--- category: swing folder: GlyphVector title: JLabelの文字列を折り返し tags: [JLabel, GlyphVector, JTextArea, LineBreakMeasurer] author: aterai pubdate: 2004-03-01T11:56:19+09:00 description: GlyphVectorを使って、ラベルの文字列を折り返して表示します。 image: https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTNbQw2SHI/AAAAAAAAAaw/AApL8KKml8E/s800/GlyphVector.png --- * 概要 [#summary] `GlyphVector`を使って、ラベルの文字列を折り返して表示します。 #download(https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTNbQw2SHI/AAAAAAAAAaw/AApL8KKml8E/s800/GlyphVector.png) * サンプルコード [#sourcecode] #code(link){{ class WrappedLabel extends JLabel { private GlyphVector gvtext; private int width = -1; public WrappedLabel() { this(null); } public WrappedLabel(String str) { super(str); } @Override public void doLayout() { Insets i = getInsets(); int w = getWidth() - i.left - i.right; if (w != width) { Font font = getFont(); FontMetrics fm = getFontMetrics(font); FontRenderContext frc = fm.getFontRenderContext(); gvtext = getWrappedGlyphVector(getText(), w, font, frc); width = w; } super.doLayout(); } @Override protected void paintComponent(Graphics g) { if (gvtext == null) { super.paintComponent(g); } else { Insets i = getInsets(); Graphics2D g2 = (Graphics2D) g.create(); g2.setPaint(Color.RED); g2.drawGlyphVector(gvtext, i.left, getFont().getSize() + i.top); g2.dispose(); } } private GlyphVector getWrappedGlyphVector( String str, float width, Font font, FontRenderContext frc) { Point2D gmPos = new Point2D.Double(0d, 0d); GlyphVector gv = font.createGlyphVector(frc, str); float lineheight = (float) (gv.getLogicalBounds().getHeight()); float xpos = 0f; float advance = 0f; int lineCount = 0; GlyphMetrics gm; for (int i = 0; i < gv.getNumGlyphs(); i++) { gm = gv.getGlyphMetrics(i); advance = gm.getAdvance(); if (xpos < width && width <= xpos + advance) { lineCount++; xpos = 0f; } gmPos.setLocation(xpos, lineheight * lineCount); gv.setGlyphPosition(i, gmPos); xpos = xpos + advance; } return gv; } } }} * 解説 [#explanation] - 上: `JLabel` -- デフォルトの`JLabel`で右側が`...`で省略されている - 中: `GlyphVector` -- コンポーネントのサイズが変更されるたびに`GlyphVector`を更新して、文字列の折り返しを行っている -- 欧文などで合字(リガチャ)がある場合は、`GlyphVector gv = font.createGlyphVector(frc, str);`ではなく、[https://community.oracle.com/thread/1289266 GlyphVector bounds and kerning, ligatures | Oracle Forums]のように、`char[] chars = text.toCharArray(); GlyphVector gv = font.layoutGlyphVector(frc, chars, 0, chars.length, Font.LAYOUT_LEFT_TO_RIGHT);`とした方が良さそう - 下: `JTextArea` -- `JLabel`の`Font`と背景色を同じものに設定した編集不可の`JTextArea`を`setLineWrap(true);`として、文字列の折り返しを行っている ---- ラベルの幅ではなく、任意の場所で文字列を改行したい場合は、以下のように`JLabel`に`html`の`<br>`タグを利用したり、編集不可にした`JTextPane`、`JTextArea`などを使用します(参考: [[JTextPane、JLabelなどで複数行を表示>Swing/MultiLineLabel]])。 #code{{ label.setText("<html>文字列を適当なところで<br />折り返す。"); }} ---- `AttributedString`と`LineBreakMeasurer`を使って、文字列の折り返しを描画する方法もあります。 #code{{ class WrappingLabel extends JLabel { public WrappingLabel(String text) { super(text); } @Override protected void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g.create(); g2.setPaint(getForeground()); Insets i = getInsets(); float x = i.left; float y = i.top; int w = getWidth() - i.left - i.right; AttributedString as = new AttributedString(getText()); as.addAttribute(TextAttribute.FONT, getFont()); AttributedCharacterIterator aci = as.getIterator(); FontRenderContext frc = g2.getFontRenderContext(); LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc); while (lbm.getPosition() < aci.getEndIndex()) { TextLayout tl = lbm.nextLayout(w); tl.draw(g2, x, y + tl.getAscent()); y += tl.getDescent() + tl.getLeading() + tl.getAscent(); } g2.dispose(); } } }} * 参考リンク [#reference] //- [http://docs.oracle.com/javase/tutorial/uiswing/14painting/concepts.html How Swing Components Are Displayed] - [http://docs.oracle.com/javase/tutorial/uiswing/components/label.html How to Use Labels] - [http://docs.oracle.com/javase/jp/6/api/java/awt/font/LineBreakMeasurer.html LineBreakMeasurer (Java Platform SE 6)] * コメント [#comment] #comment - `JTextArea#setLineWrap(true);`を使う方法を追加、スクリーンショットの更新。 -- &user(aterai); &new{2009-01-05 (月) 17:15:36}; - `LineBreakMeasurer`を使用する方法を追加。 -- &user(aterai); &new{2013-01-01 (火) 22:38:47}; #comment