TITLE:JTextAreaに行番号を表示

JTextAreaに行番号を表示

編集者:Terai Atsuhiro~

作成日:2006-02-20
更新日:2021-04-09 (金) 19:42:12
  • category: swing folder: LineNumber title: JTextAreaに行番号を表示 tags: [JTextArea, FontMetrics, JScrollPane] author: aterai pubdate: 2006-02-20T20:26:20+09:00 description: JTextAreaの行番号を表示するコンポーネントを作成し、これを対象となるJTextAreaと同じJScrollPaneのRowHeaderViewに設定します。 image: https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTPV_bkDWI/AAAAAAAAAd0/Jktuzx5j5gU/s800/LineNumber.png

概要

JTextAreaの行番号を表示するコンポーネントを作成し、これを対象となるJTextAreaと同じJScrollPaneRowHeaderViewに設定します。

概要

JTextAreaに行番号を表示します。

サンプルコード

#spanend
#spanadd
class LineNumberView extends JComponent {
#spanend
  private static final int MARGIN = 5;
  private final JTextArea textArea;
  private final FontMetrics fontMetrics;
  // private final int topInset;
  private final int fontAscent;
  private final int fontHeight;
  private final int fontDescent;
  private final int fontLeading;

#spandel
#screenshot
#spanend
  public LineNumberView(JTextArea textArea) {
    this.textArea = textArea;
    Font font = textArea.getFont();
    fontMetrics = getFontMetrics(font);
    fontHeight = fontMetrics.getHeight();
    fontAscent = fontMetrics.getAscent();
    fontDescent = fontMetrics.getDescent();
    fontLeading = fontMetrics.getLeading();
    // topInset = textArea.getInsets().top;

#spandel
**サンプルコード [#caf6edeb]
#spanend
#spandel
#code{{
#spanend
 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() {
       public void insertUpdate(DocumentEvent e) {
         repaint();
       }
       public void removeUpdate(DocumentEvent e) {
         repaint();
       }
       public void changedUpdate(DocumentEvent e) {}
     });
     text.addComponentListener(new ComponentAdapter() {
       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);
   }
   public Dimension getPreferredSize() {
     return new Dimension(getComponentWidth(), text.getHeight());
   }
   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);
     }
   }
 }
    textArea.getDocument().addDocumentListener(new DocumentListener() {
      @Override public void insertUpdate(DocumentEvent e) {
        repaint();
      }
#spanadd

#spanend
      @Override public void removeUpdate(DocumentEvent e) {
        repaint();
      }
#spanadd

#spanend
      @Override public void changedUpdate(DocumentEvent e) {
        // repaint();
      }
    });
    textArea.addComponentListener(new ComponentAdapter() {
      @Override public void componentResized(ComponentEvent e) {
        revalidate();
        repaint();
      }
    });
    Insets i = textArea.getInsets();
    setBorder(BorderFactory.createCompoundBorder(
      BorderFactory.createMatteBorder(0, 0, 0, 1, Color.GRAY),
      BorderFactory.createEmptyBorder(i.top, MARGIN, i.bottom, MARGIN - 1)));
    setOpaque(true);
    setBackground(Color.WHITE);
    setFont(font);
  }
#spanadd

#spanend
  private int getComponentWidth() {
    Document doc = textArea.getDocument();
    Element root = doc.getDefaultRootElement();
    int lineCount = root.getElementIndex(doc.getLength());
    int maxDigits = Math.max(3, String.valueOf(lineCount).length());
    Insets i = getInsets();
    return maxDigits * fontMetrics.stringWidth("0") + i.left + i.right;
    // return 48;
  }
#spanadd

#spanend
  private int getLineAtPoint(int y) {
    Element root = textArea.getDocument().getDefaultRootElement();
    int pos = textArea.viewToModel(new Point(0, y));
    return root.getElementIndex(pos);
  }
#spanadd

#spanend
  @Override public Dimension getPreferredSize() {
    return new Dimension(getComponentWidth(), textArea.getHeight());
  }
#spanadd

#spanend
  @Override protected void paintComponent(Graphics g) {
    g.setColor(getBackground());
    Rectangle clip = g.getClipBounds();
    g.fillRect(clip.x, clip.y, clip.width, clip.height);
#spanadd

#spanend
    g.setColor(getForeground());
    int base = clip.y;
    int start = getLineAtPoint(base);
    int end = getLineAtPoint(base + clip.height);
    int y = start * fontHeight;
    int rmg = getInsets().right;
    for (int i = start; i <= end; i++) {
      String text = String.valueOf(i + 1);
      int x = getComponentWidth() - rmg - fontMetrics.stringWidth(text);
      y += fontAscent;
      g.drawString(text, x, y);
      y += fontDescent + fontLeading;
    }
  }
#spanadd
}
#spanend
View in GitHub: Java, Kotlin
  • &jnlp;
  • &jar;
  • &zip;

解説

Line Number in JTextPaneを参考にして、JTextAreaに行番号を表示しています。

解説

Swing (Archive) - Advice for editor gutter implementation...を参考にして、JTextAreaに行番号を表示しています。 上記のサンプルで使用するJTextAreaは、行の高さはすべて一定で、フォントや余白などは変更されないものと想定しています。 上記のサンプルで使用するJTextAreaは、使用するフォントや余白などは変更不可で各行の高さはすべて同一で不変と想定しています。

参考リンク

コメント

  • すごいね!私はこのような資料を探しています、どうも ありがとうございます。 -- CK

参考リンク

コメント