• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:JTextAreaに行番号を表示
#navi(../)
#tags()
#tags(JTextArea, FontMetrics)
RIGHT:Posted by &author(aterai); at 2006-02-20
*JTextAreaに行番号を表示 [#l3a54503]
JTextAreaに行番号を表示します。
``JTextArea``に行番号を表示します。

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

//#screenshot
#ref(http://lh4.ggpht.com/_9Z4BYR88imo/TQTPV_bkDWI/AAAAAAAAAd0/Jktuzx5j5gU/s800/LineNumber.png)

**サンプルコード [#caf6edeb]
#code(link){{
class LineNumberView extends JComponent {
  private static final int MARGIN = 5;
  private final JTextArea text;
  private final FontMetrics fontMetrics;
  private final int topInset;
  private final int fontAscent;
  private final int fontHeight;
  public LineNumberView(JTextArea textArea) {
    text        = textArea;
    fontMetrics = getFontMetrics(text.getFont());
    fontHeight  = fontMetrics.getHeight();
    fontAscent  = fontMetrics.getAscent();
    topInset    = text.getInsets().top;
    text.getDocument().addDocumentListener(new DocumentListener() {
      @Override public void insertUpdate(DocumentEvent e) {
        repaint();
      }
      @Override public void removeUpdate(DocumentEvent e) {
        repaint();
      }
      @Override public void changedUpdate(DocumentEvent e) {}
    });
    text.addComponentListener(new ComponentAdapter() {
      @Override public void componentResized(ComponentEvent e) {
        revalidate();
        repaint();
      }
    });
    setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, Color.GRAY));
  }
  private int getComponentWidth() {
    Document doc  = text.getDocument();
    Element root  = doc.getDefaultRootElement();
    int lineCount = root.getElementIndex(doc.getLength());
    int maxDigits = Math.max(3, String.valueOf(lineCount).length());
    return maxDigits*fontMetrics.stringWidth("0")+MARGIN*2;
  }
  private int getLineAtPoint(int y) {
    Element root = text.getDocument().getDefaultRootElement();
    int pos = text.viewToModel(new Point(0, y));
    return root.getElementIndex(pos);
  }
  @Override public Dimension getPreferredSize() {
    return new Dimension(getComponentWidth(), text.getHeight());
  }
  @Override public void paintComponent(Graphics g) {
    Rectangle clip = g.getClipBounds();
    g.setColor(getBackground());
    g.fillRect(clip.x, clip.y, clip.width, clip.height);
    g.setColor(getForeground());
    int base  = clip.y - topInset;
    int start = getLineAtPoint(base);
    int end   = getLineAtPoint(base+clip.height);
    int y = topInset-fontHeight+fontAscent+start*fontHeight;
    for(int i=start;i<=end;i++) {
      String text = String.valueOf(i+1);
      int x = getComponentWidth()-MARGIN-fontMetrics.stringWidth(text);
      y = y + fontHeight;
      g.drawString(text, x, y);
    }
  }
}
}}

**解説 [#mcee74d1]
[http://forums.sun.com/thread.jspa?threadID=585673 Swing - Line Number in JTextPane]を参考にして、JTextAreaに行番号を表示しています。
[http://forums.sun.com/thread.jspa?threadID=585673 Swing - Line Number in JTextPane]を参考にして、``JTextArea``に行番号を表示しています。

上記のサンプルで使用するJTextAreaは、使用するフォントや余白などは変更不可で、各行の高さは最後まで一定であると想定しています。
上記のサンプルで使用する``JTextArea``は、使用するフォントや余白などは変更不可で、各行の高さは最後まで一定であると想定しています。

**参考リンク [#qeacb6f7]
-[http://forums.sun.com/thread.jspa?threadID=585673 Swing - Line Number in JTextPane]
-[http://forums.sun.com/thread.jspa?threadID=422802 Swing (Archive) - line number in jtextpane]

**コメント [#eb1fb225]
- すごいね!私はこのような資料を探しています、どうも ありがとうございます。 -- [[CK]] &new{2007-04-21 (Sat) 18:29:31};
-- どういたしまして。 -- [[aterai]] &new{2007-04-23 (月) 09:47:47};
- こちらのソースは非常に参考になります。現在趣味でエディタを作成しているのですが、JTextPaneのDocumentをJTextAreaに与えてカーソル位置を取得しています。JTextPaneで行番号、列番号を正確に取得できないものでしょうか? -- [[shusen]] &new{2007-11-09 (金) 10:22:30};
- どうもです。JTextPaneだと、行の折り返しをどう扱うかで、行番号の表示が異なります。   -- [[aterai]] &new{2007-11-09 (金) 14:52:40};
- こちらのソースは非常に参考になります。現在趣味でエディタを作成しているのですが、``JTextPane``の``Document``を``JTextArea``に与えてカーソル位置を取得しています。``JTextPane``で行番号、列番号を正確に取得できないものでしょうか? -- [[shusen]] &new{2007-11-09 (金) 10:22:30};
- どうもです。``JTextPane``だと、行の折り返しをどう扱うかで、行番号の表示が異なります。   -- [[aterai]] &new{2007-11-09 (金) 14:52:40};
--折り返しても表示は前の行のままの場合
---[http://forums.sun.com/thread.jspa?threadID=585673 Swing - Line Number in JTextPane]
---このページのサンプルは、上記のリンク先にあるLineNumberView(@author Alan Moore)を参考にしていますが、JTextAreaに必要なさそうな折り返しや各行の高さが異なる場合などの処理を削っているので、JTextPaneで使う場合は、リンク先などのオリジナルのソースを参考にしてください。
---このページのサンプルは、上記のリンク先にある``LineNumberView``(@author Alan Moore)を参考にしていますが、``JTextArea``に必要なさそうな折り返しや各行の高さが異なる場合などの処理を削っているので、``JTextPane``で使う場合は、リンク先などのオリジナルのソースを参考にしてください。
--折り返された行にも行番号を表示したい場合
---[http://forums.sun.com/thread.jspa?threadID=422802 Swing (Archive) - line number in jtextpane]
---上記のリンク先にあるサンプルでは、EditorKitを使って行番号を表示しており、JTextPaneで折り返された行でも、表示に従って行番号が割り振られています。
- ご返答ありがとうございます。現在はこちらにある折り返し抑制のソースを利用させていただいているので、EditorKitを利用する分を試してみたいと思います。 -- [[shusen]] &new{2007-11-09 (金) 19:16:05};
- EditorKitを利用した分をコピペして、とりあえずそのままコンパイル・実行してみました。ここでおかしいことがありまして、コマンドプロンプトから起動すると文字が挿入された行のみ行番号が表示されるのですが、自作エディタからProcessBuilderとProcessで"java Test"となるように呼び出すと、未入力の行も含めて全ての行番号が表示されます。コレはプロンプトの実効環境がおかしいのでしょうか? -- [[shusen]] &new{2007-11-14 (水) 17:20:54};
- すみません、自己解決しました(たぶん)。ランタイムの問題で、jre1.6.0_01以下だと上記の状態になりました。jre1.6.0_02とjre1.6.0_03ではちゃんと表示されました。 -- [[shusen]] &new{2007-11-14 (水) 17:31:45};
-- ども。直接は関係のない話ですが、バージョンかぁと何気にダウンロードサイトに行ったら、%%サーバー落ちてるっぽいですねorz%% あとで見たらダウンロードのページがすこし変更されているみたいなので、単に更新中だっただけみたいです。 -- [[aterai]] &new{2007-11-14 (水) 18:43:29};
---上記のリンク先にあるサンプルでは、``EditorKit``を使って行番号を表示しており、``JTextPane``で折り返された行でも、表示に従って行番号が割り振られています。
- ご返答ありがとうございます。現在はこちらにある折り返し抑制のソースを利用させていただいているので、``EditorKit``を利用する分を試してみたいと思います。 -- [[shusen]] &new{2007-11-09 (金) 19:16:05};
- ``EditorKit``を利用した分をコピペして、とりあえずそのままコンパイル・実行してみました。ここでおかしいことがありまして、コマンドプロンプトから起動すると文字が挿入された行のみ行番号が表示されるのですが、自作エディタから``ProcessBuilder``と``Process``で``"java Test"``となるように呼び出すと、未入力の行も含めて全ての行番号が表示されます。コレはプロンプトの実効環境がおかしいのでしょうか? -- [[shusen]] &new{2007-11-14 (水) 17:20:54};
- すみません、自己解決しました(たぶん)。ランタイムの問題で、``jre1.6.0_01``以下だと上記の状態になりました。``jre1.6.0_02``と``jre1.6.0_03``ではちゃんと表示されました。 -- [[shusen]] &new{2007-11-14 (水) 17:31:45};
-- 情報ありがとうございます。直接は関係のない話ですが、バージョンかぁと何気にダウンロードサイトに行ったら、%%サーバー落ちてるっぽいですねorz%% あとで見たらダウンロードのページがすこし変更されているみたいなので、単に更新中だっただけ?みたいです。 -- [[aterai]] &new{2007-11-14 (水) 18:43:29};

#comment