Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 12 of 12

Thread: How To: Add line numbers to your JTextArea

  1. #1
    Senile Half-Wit Freaky Chris's Avatar
    Join Date
    Mar 2009
    Location
    Wales, Bangor & England, Warwickshire
    Posts
    820
    My Mood
    Cynical
    Thanks
    7
    Thanked 104 Times in 90 Posts

    Default How To: Add line numbers to your JTextArea

    Well, I know a few people have wanted to do things like this before. So here is my code approach to it, enjoy. There are other methods I'm sure, but I think this is the easiest.

    It makes use of the JScrollPane Row Header

    import java.awt.Color;
     
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.event.DocumentEvent;
    import javax.swing.event.DocumentListener;
    import javax.swing.text.Element;
     
     
    public class LineNumbering extends JFrame{
    	private static JTextArea jta;
    	private static JTextArea lines;
     
    	public LineNumbering(){
    		super("Line Numbering Example");
    	}
     
    	public static void createAndShowGUI(){
    		JFrame frame = new LineNumbering();
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		JScrollPane jsp = new JScrollPane();
    		jta = new JTextArea();
    		lines = new JTextArea("1");
     
    		lines.setBackground(Color.LIGHT_GRAY);
    		lines.setEditable(false);
     
    		jta.getDocument().addDocumentListener(new DocumentListener(){
    			public String getText(){
    				int caretPosition = jta.getDocument().getLength();
    				Element root = jta.getDocument().getDefaultRootElement();
    				String text = "1" + System.getProperty("line.separator");
    				for(int i = 2; i < root.getElementIndex( caretPosition ) + 2; i++){
    					text += i + System.getProperty("line.separator");
    				}
    				return text;
    			}
    			@Override
    			public void changedUpdate(DocumentEvent de) {
    				lines.setText(getText());
    			}
     
    			@Override
    			public void insertUpdate(DocumentEvent de) {
    				lines.setText(getText());
    			}
     
    			@Override
    			public void removeUpdate(DocumentEvent de) {
    				lines.setText(getText());
    			}
     
    		});
     
    		jsp.getViewport().add(jta);
    		jsp.setRowHeaderView(lines);
    		jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
     
    		frame.add(jsp);
    		frame.pack();
    		frame.setSize(500,500);
    		frame.setVisible(true);
    	}
     
    	public static void main(String[] args){
    		javax.swing.SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    createAndShowGUI();
                }
            });
    	}
    }

    Chris
    chris[at]javaprogrammingforums[dot]com

    Prifysgol Bangor University, North Wales

  2. The Following 5 Users Say Thank You to Freaky Chris For This Useful Post:

    AdiRat (February 23rd, 2010), Bubumuk (March 4th, 2011), JavaPF (September 17th, 2009), Json (September 11th, 2009), neo_2010 (September 30th, 2009)


  3. #2
    Junior Member
    Join Date
    Jul 2009
    Location
    SomeWhere in the world
    Posts
    27
    Thanks
    1
    Thanked 11 Times in 6 Posts

    Default Re: How To: Add line numbers to your JTextArea

    very good one...thanks a lot
    On the way to be Master...

  4. #3
    Senile Half-Wit Freaky Chris's Avatar
    Join Date
    Mar 2009
    Location
    Wales, Bangor & England, Warwickshire
    Posts
    820
    My Mood
    Cynical
    Thanks
    7
    Thanked 104 Times in 90 Posts

    Default Re: How To: Add line numbers to your JTextArea

    Glad you guys like it, would you like me to see about adding line highlighting when you click the line number and things?

    Regards,
    Chris
    chris[at]javaprogrammingforums[dot]com

    Prifysgol Bangor University, North Wales

  5. #4
    Junior Member
    Join Date
    Sep 2009
    Posts
    9
    Thanks
    2
    Thanked 1 Time in 1 Post

    Default Re: How To: Add line numbers to your JTextArea

    Thanks !!!

  6. #5
    Junior Member
    Join Date
    Feb 2010
    Posts
    2
    Thanks
    1
    Thanked 0 Times in 0 Posts

    Default Re: How To: Add line numbers to your JTextArea

    This very useful code. Also, that line highlighting sounds pretty interesting... If you have enough time, can you implement it, please?

    Thanks you very much

  7. #6
    Senile Half-Wit Freaky Chris's Avatar
    Join Date
    Mar 2009
    Location
    Wales, Bangor & England, Warwickshire
    Posts
    820
    My Mood
    Cynical
    Thanks
    7
    Thanked 104 Times in 90 Posts

    Default Re: How To: Add line numbers to your JTextArea

    OK, so this seemed to be a popular code snippet, and with a request of highlighting i have decided to actually do it. Sorry it took so longer but here it is.

    import java.awt.Color;
    import java.awt.event.FocusEvent;
    import java.awt.event.FocusListener;
    import java.awt.event.MouseEvent;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.event.DocumentEvent;
    import javax.swing.event.DocumentListener;
    import javax.swing.event.MouseInputListener;
    import javax.swing.text.BadLocationException;
    import javax.swing.text.Element;
    import javax.swing.text.Highlighter;
     
     
    public class MainWindow extends JFrame implements MouseInputListener, DocumentListener, FocusListener{
    	private JTextArea jta;
    	private JTextArea lines;
    	private Highlighter highlighter;
     
    	public MainWindow(){
    		super("Line Numbering & Highlighter Example");
    	}
    	public void createAndShowGUI(){
    		/* Set up frame */
    		JFrame frame = new MainWindow();
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		/* Set up JtextArea */
    		jta = new JTextArea();
    		jta.getDocument().addDocumentListener(this);
     
    		/* Set up Highlighter */
    		highlighter = jta.getHighlighter();
     
    		/* Set up line numbers */
    		lines = new JTextArea("1");
    		lines.setBackground(Color.LIGHT_GRAY);
    		lines.setEditable(false);
    		lines.addMouseListener(this);
    		lines.addFocusListener(this);
     
    		/* Set up scroll pane */
    		JScrollPane jsp = new JScrollPane();
    		jsp.getViewport().add(jta);
    		jsp.setRowHeaderView(lines);
    		jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
     
    		jta.setText("Hello world how are you today!");
     
    		/* pack and show frame */
    		frame.add(jsp);
    		frame.pack();
    		frame.setSize(500,500);
    		frame.setVisible(true);
    	}
     
    	/* Document Listener Events */
    	public void changedUpdate(DocumentEvent de) {
    		lines.setText(getText());
    	}
    	public void insertUpdate(DocumentEvent de) {
    		lines.setText(getText());
    	}
    	public void removeUpdate(DocumentEvent de) {
    		lines.setText(getText());
    	}
    	public String getText(){
    		int caretPosition = jta.getDocument().getLength();
    		Element root = jta.getDocument().getDefaultRootElement();
    		String text = "1\n";
    		for(int i = 2; i < root.getElementIndex( caretPosition ) + 2; i++)
    			text += i + "\n";
    		return text;
    	}
     
    	/* Mouse Listener Events */
    	public void mouseClicked(MouseEvent me) {
    		if(me.getClickCount() == 2){
    			try {
    				int caretPos = lines.getCaretPosition();
    				int lineOffset = lines.getLineOfOffset(caretPos);
    				if(lines.getText().charAt(caretPos-1) == '\n')
    					lineOffset--;
    				highlighter.addHighlight(jta.getLineStartOffset(lineOffset),
    										 jta.getLineEndOffset(lineOffset), 
    										 new MyHighlighter(Color.cyan));
    			} catch (BadLocationException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    	public void mouseEntered(MouseEvent me) {}
    	public void mouseExited(MouseEvent me) {}
    	public void mousePressed(MouseEvent me) {}
    	public void mouseReleased(MouseEvent me) {}
    	public void mouseDragged(MouseEvent me) {}
    	public void mouseMoved(MouseEvent me) {}
     
    	/* Focus Listener Events for line numbers*/
    	public void focusGained(FocusEvent fe) {}
    	public void focusLost(FocusEvent fe) {
    		highlighter.removeAllHighlights();
    	}
    	public static void main(String[] args){
    		javax.swing.SwingUtilities.invokeLater(new Runnable() {
                                                       public void run() {
                                                                  new MainWindow().createAndShowGUI();
                                                       }
                                               });
    	}
    }
    [/code]
    [code]
    import java.awt.Color;
    import javax.swing.text.DefaultHighlighter;
     
    public class MyHighlighter extends DefaultHighlighter.DefaultHighlightPainter {
    	public MyHighlighter(Color c) {
    		super(c);
    	}
    }

    Enjoy,

    Chris
    Last edited by Freaky Chris; October 15th, 2010 at 05:37 AM.
    chris[at]javaprogrammingforums[dot]com

    Prifysgol Bangor University, North Wales

  8. #7
    Junior Member
    Join Date
    Aug 2010
    Posts
    1
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default Re: How To: Add line numbers to your JTextArea

    Quote Originally Posted by Freaky Chris View Post
    Well, I know a few people have wanted to do things like this before. So here is my code approach to it, enjoy. There are other methods I'm sure, but I think this is the easiest.

    It makes use of the JScrollPane Row Header

    import java.awt.Color;
     
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.event.DocumentEvent;
    import javax.swing.event.DocumentListener;
    import javax.swing.text.Element;
     
     
    public class LineNumbering extends JFrame{
    	private static JTextArea jta;
    	private static JTextArea lines;
     
    	public LineNumbering(){
    		super("Line Numbering Example");
    	}
     
    	public static void createAndShowGUI(){
    		JFrame frame = new LineNumbering();
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		JScrollPane jsp = new JScrollPane();
    		jta = new JTextArea();
    		lines = new JTextArea("1");
     
    		lines.setBackground(Color.LIGHT_GRAY);
    		lines.setEditable(false);
     
    		jta.getDocument().addDocumentListener(new DocumentListener(){
    			public String getText(){
    				int caretPosition = jta.getDocument().getLength();
    				Element root = jta.getDocument().getDefaultRootElement();
    				String text = "1" + System.getProperty("line.separator");
    				for(int i = 2; i < root.getElementIndex( caretPosition ) + 2; i++){
    					text += i + System.getProperty("line.separator");
    				}
    				return text;
    			}
    			@Override
    			public void changedUpdate(DocumentEvent de) {
    				lines.setText(getText());
    			}
     
    			@Override
    			public void insertUpdate(DocumentEvent de) {
    				lines.setText(getText());
    			}
     
    			@Override
    			public void removeUpdate(DocumentEvent de) {
    				lines.setText(getText());
    			}
     
    		});
     
    		jsp.getViewport().add(jta);
    		jsp.setRowHeaderView(lines);
    		jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
     
    		frame.add(jsp);
    		frame.pack();
    		frame.setSize(500,500);
    		frame.setVisible(true);
    	}
     
    	public static void main(String[] args){
    		javax.swing.SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    createAndShowGUI();
                }
            });
    	}
    }

    Chris
    Thnks dis helped me a lot but could u plz provide some explanation abt dis code would of greta help.....

  9. #8
    Junior Member
    Join Date
    Oct 2009
    Posts
    4
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default Re: How To: Add line numbers to your JTextArea

    Good code.

  10. #9
    Senile Half-Wit Freaky Chris's Avatar
    Join Date
    Mar 2009
    Location
    Wales, Bangor & England, Warwickshire
    Posts
    820
    My Mood
    Cynical
    Thanks
    7
    Thanked 104 Times in 90 Posts

    Default Re: How To: Add line numbers to your JTextArea

    I'm glad people are finding this useful, again I will develop this further upon request by members.


    Thanks Guys
    chris[at]javaprogrammingforums[dot]com

    Prifysgol Bangor University, North Wales

  11. #10
    Junior Member
    Join Date
    Mar 2011
    Posts
    1
    Thanks
    1
    Thanked 0 Times in 0 Posts

    Default Re: How To: Add line numbers to your JTextArea

    Quote Originally Posted by Freaky Chris View Post
    Well, I know a few people have wanted to do things like this before. So here is my code approach to it, enjoy. There are other methods I'm sure, but I think this is the easiest.

    It makes use of the JScrollPane Row Header

    import java.awt.Color;
     
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.event.DocumentEvent;
    import javax.swing.event.DocumentListener;
    import javax.swing.text.Element;
     
     
    public class LineNumbering extends JFrame{
    	private static JTextArea jta;
    	private static JTextArea lines;
     
    	public LineNumbering(){
    		super("Line Numbering Example");
    	}
     
    	public static void createAndShowGUI(){
    		JFrame frame = new LineNumbering();
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		JScrollPane jsp = new JScrollPane();
    		jta = new JTextArea();
    		lines = new JTextArea("1");
     
    		lines.setBackground(Color.LIGHT_GRAY);
    		lines.setEditable(false);
     
    		jta.getDocument().addDocumentListener(new DocumentListener(){
    			public String getText(){
    				int caretPosition = jta.getDocument().getLength();
    				Element root = jta.getDocument().getDefaultRootElement();
    				String text = "1" + System.getProperty("line.separator");
    				for(int i = 2; i < root.getElementIndex( caretPosition ) + 2; i++){
    					text += i + System.getProperty("line.separator");
    				}
    				return text;
    			}
    			@Override
    			public void changedUpdate(DocumentEvent de) {
    				lines.setText(getText());
    			}
     
    			@Override
    			public void insertUpdate(DocumentEvent de) {
    				lines.setText(getText());
    			}
     
    			@Override
    			public void removeUpdate(DocumentEvent de) {
    				lines.setText(getText());
    			}
     
    		});
     
    		jsp.getViewport().add(jta);
    		jsp.setRowHeaderView(lines);
    		jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
     
    		frame.add(jsp);
    		frame.pack();
    		frame.setSize(500,500);
    		frame.setVisible(true);
    	}
     
    	public static void main(String[] args){
    		javax.swing.SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    createAndShowGUI();
                }
            });
    	}
    }

    Chris
    Hello! I have a doubt.
    Everytime I modify the text in the JTextArea, the "number area" updates and scrolls down to the end. I mean, if I write a character at line 67 out of 100, the "line number area" shows me 95 96 97 98 99 100... just the end and it doesn't stays at that line number (67 in this case).

    How can I fix that? I'm kind of stuck there.

    I hope you can help me.
    Thanks.

  12. #11
    Junior Member
    Join Date
    Mar 2011
    Location
    Germany
    Posts
    1
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default Re: How To: Add line numbers to your JTextArea

    hi all,

    i am new to this forum, so at first i just want so say hello to all :-)

    i have a little project implementing some own grammar language
    for some german linguists and want to have a nice little IDE
    to edit those grammars ...
    so i startet to create some basic IDE features with swing
    an netbeans.
    i used the code here and found, which seems very helpful for me,
    but i also noticed some problems ...

    1. display of linenumbers
    in some circumstances the scrolling of the editor component and the
    line header in scoll bar are not synchronized.
    which means scrolling posion is not the same and the displayed lineno
    does not represent the actual one ...
    i currently not know how to sync theese components ... :-(

    2. jtextpane and linewrap
    for syntaxhighlighing functions i need jtextpane insted of
    jtextarea.
    out of the box you can't easly turnoff linewrapping in jtextpane.
    if you use a little trick and enclose the jtextpane in a pane which
    layout is set to 'border' you can simulate no line wrap.
    the problem is, if you type out of the viewport you cant see the edit-
    cursor, which is out of the viewport ...
    maybe this also have to be synced somehow with scrolling ...

    maybe anybody has a great idea or some useful experience on this :-)

    thank you in andvance

    regards
    patrick

  13. #12
    Member GoodbyeWorld's Avatar
    Join Date
    Jul 2012
    Location
    Hidden command post deep within the bowels of a hidden bunker somewhere under a nondescrip building
    Posts
    319
    My Mood
    Angry
    Thanks
    39
    Thanked 50 Times in 50 Posts

    Default Re: How To: Add line numbers to your JTextArea

    That one is good, though it doesn't work well with different font sizes and was ending too short of the actual end line. This code I found online works better.

     
     
    import java.awt.*;
    import java.awt.event.*;
    import java.beans.*;
    import java.util.HashMap;
    import javax.swing.*;
    import javax.swing.border.*;
    import javax.swing.event.*;
    import javax.swing.text.*;
     
    /**
     *  This class will display line numbers for a related text component. The text
     *  component must use the same line height for each line. TextLineNumber
     *  supports wrapped lines and will highlight the line number of the current
     *  line in the text component.
     *
     *  This class was designed to be used as a component added to the row header
     *  of a JScrollPane.
     */
    public class TextLineNumber extends JPanel
    	implements CaretListener, DocumentListener, PropertyChangeListener
    {
       public final static float LEFT = 0.0f;
       public final static float CENTER = 0.5f;
       public final static float RIGHT = 1.0f;
     
       private final static Border OUTER = new MatteBorder(0, 0, 0, 2, Color.GRAY);
     
       private final static int HEIGHT = Integer.MAX_VALUE - 1000000;
     
    	//  Text component this TextTextLineNumber component is in sync with
     
       private JTextComponent component;
     
    	//  Properties that can be changed
     
       private boolean updateFont;
       private int borderGap;
       private Color currentLineForeground;
       private float digitAlignment;
       private int minimumDisplayDigits;
     
    	//  Keep history information to reduce the number of times the component
    	//  needs to be repainted
     
       private int lastDigits;
       private int lastHeight;
       private int lastLine;
     
       private HashMap<String, FontMetrics> fonts;
     
    	/**
    	 *	Create a line number component for a text component. This minimum
    	 *  display width will be based on 3 digits.
    	 *
    	 *  @param component  the related text component
    	 */
       public TextLineNumber(JTextComponent component)
       {
          this(component, 3);
       }
     
    	/**
    	 *	Create a line number component for a text component.
    	 *
    	 *  @param component  the related text component
    	 *  @param minimumDisplayDigits  the number of digits used to calculate
    	 *                               the minimum width of the component
    	 */
       public TextLineNumber(JTextComponent component, int minimumDisplayDigits)
       {
          this.component = component;
     
          setFont( component.getFont() );
     
          setBorderGap( 5 );
          setCurrentLineForeground( Color.RED );
          setDigitAlignment( RIGHT );
          setMinimumDisplayDigits( minimumDisplayDigits );
     
          component.getDocument().addDocumentListener(this);
          component.addCaretListener( this );
          component.addPropertyChangeListener("font", this);
       }
     
    	/**
    	 *  Gets the update font property
    	 *
    	 *  @return the update font property
    	 */
       public boolean getUpdateFont()
       {
          return updateFont;
       }
     
    	/**
    	 *  Set the update font property. Indicates whether this Font should be
    	 *  updated automatically when the Font of the related text component
    	 *  is changed.
    	 *
    	 *  @param updateFont  when true update the Font and repaint the line
    	 *                     numbers, otherwise just repaint the line numbers.
    	 */
       public void setUpdateFont(boolean updateFont)
       {
          this.updateFont = updateFont;
       }
     
    	/**
    	 *  Gets the border gap
    	 *
    	 *  @return the border gap in pixels
    	 */
       public int getBorderGap()
       {
          return borderGap;
       }
     
    	/**
    	 *  The border gap is used in calculating the left and right insets of the
    	 *  border. Default value is 5.
    	 *
    	 *  @param borderGap  the gap in pixels
    	 */
       public void setBorderGap(int borderGap)
       {
          this.borderGap = borderGap;
          Border inner = new EmptyBorder(0, borderGap, 0, borderGap);
          setBorder( new CompoundBorder(OUTER, inner) );
          lastDigits = 0;
          setPreferredWidth();
       }
     
    	/**
    	 *  Gets the current line rendering Color
    	 *
    	 *  @return the Color used to render the current line number
    	 */
       public Color getCurrentLineForeground()
       {
          return currentLineForeground == null ? getForeground() : currentLineForeground;
       }
     
    	/**
    	 *  The Color used to render the current line digits. Default is Coolor.RED.
    	 *
    	 *  @param currentLineForeground  the Color used to render the current line
    	 */
       public void setCurrentLineForeground(Color currentLineForeground)
       {
          this.currentLineForeground = currentLineForeground;
       }
     
    	/**
    	 *  Gets the digit alignment
    	 *
    	 *  @return the alignment of the painted digits
    	 */
       public float getDigitAlignment()
       {
          return digitAlignment;
       }
     
    	/**
    	 *  Specify the horizontal alignment of the digits within the component.
    	 *  Common values would be:
    	 *  <ul>
    	 *  <li>TextLineNumber.LEFT
    	 *  <li>TextLineNumber.CENTER
    	 *  <li>TextLineNumber.RIGHT (default)
    	 *	</ul>
    	 *  @param currentLineForeground  the Color used to render the current line
    	 */
       public void setDigitAlignment(float digitAlignment)
       {
          this.digitAlignment =
             digitAlignment > 1.0f ? 1.0f : digitAlignment < 0.0f ? -1.0f : digitAlignment;
       }
     
    	/**
    	 *  Gets the minimum display digits
    	 *
    	 *  @return the minimum display digits
    	 */
       public int getMinimumDisplayDigits()
       {
          return minimumDisplayDigits;
       }
     
    	/**
    	 *  Specify the mimimum number of digits used to calculate the preferred
    	 *  width of the component. Default is 3.
    	 *
    	 *  @param minimumDisplayDigits  the number digits used in the preferred
    	 *                               width calculation
    	 */
       public void setMinimumDisplayDigits(int minimumDisplayDigits)
       {
          this.minimumDisplayDigits = minimumDisplayDigits;
          setPreferredWidth();
       }
     
    	/**
    	 *  Calculate the width needed to display the maximum line number
    	 */
       private void setPreferredWidth()
       {
          Element root = component.getDocument().getDefaultRootElement();
          int lines = root.getElementCount();
          int digits = Math.max(String.valueOf(lines).length(), minimumDisplayDigits);
     
       	//  Update sizes when number of digits in the line number changes
     
          if (lastDigits != digits)
          {
             lastDigits = digits;
             FontMetrics fontMetrics = getFontMetrics( getFont() );
             int width = fontMetrics.charWidth( '0' ) * digits;
             Insets insets = getInsets();
             int preferredWidth = insets.left + insets.right + width;
     
             Dimension d = getPreferredSize();
             d.setSize(preferredWidth, HEIGHT);
             setPreferredSize( d );
             setSize( d );
          }
       }
     
    	/**
    	 *  Draw the line numbers
    	 */
       @Override
       public void paintComponent(Graphics g)
       {
          super.paintComponent(g);
     
       	//	Determine the width of the space available to draw the line number
     
          FontMetrics fontMetrics = component.getFontMetrics( component.getFont() );
          Insets insets = getInsets();
          int availableWidth = getSize().width - insets.left - insets.right;
     
       	//  Determine the rows to draw within the clipped bounds.
     
          java.awt.Rectangle clip = g.getClipBounds();
          int rowStartOffset = component.viewToModel( new Point(0, clip.y) );
          int endOffset = component.viewToModel( new Point(0, clip.y + clip.height) );
     
          while (rowStartOffset <= endOffset)
          {
             try
             {
                if (isCurrentLine(rowStartOffset))
                   g.setColor( getCurrentLineForeground() );
                else
                   g.setColor( getForeground() );
     
             	//  Get the line number as a string and then determine the
             	//  "X" and "Y" offsets for drawing the string.
     
                String lineNumber = getTextLineNumber(rowStartOffset);
                int stringWidth = fontMetrics.stringWidth( lineNumber );
                int x = getOffsetX(availableWidth, stringWidth) + insets.left;
                int y = getOffsetY(rowStartOffset, fontMetrics);
                g.drawString(lineNumber, x, y);
     
             	//  Move to the next row
     
                rowStartOffset = Utilities.getRowEnd(component, rowStartOffset) + 1;
             }
             catch(Exception e) {
                break;}
          }
       }
     
    	/*
    	 *  We need to know if the caret is currently positioned on the line we
    	 *  are about to paint so the line number can be highlighted.
    	 */
       private boolean isCurrentLine(int rowStartOffset)
       {
          int caretPosition = component.getCaretPosition();
          Element root = component.getDocument().getDefaultRootElement();
     
          if (root.getElementIndex( rowStartOffset ) == root.getElementIndex(caretPosition))
             return true;
          else
             return false;
       }
     
    	/*
    	 *	Get the line number to be drawn. The empty string will be returned
    	 *  when a line of text has wrapped.
    	 */
       protected String getTextLineNumber(int rowStartOffset)
       {
          Element root = component.getDocument().getDefaultRootElement();
          int index = root.getElementIndex( rowStartOffset );
          Element line = root.getElement( index );
     
          if (line.getStartOffset() == rowStartOffset)
             return String.valueOf(index + 1);
          else
             return "";
       }
     
    	/*
    	 *  Determine the X offset to properly align the line number when drawn
    	 */
       private int getOffsetX(int availableWidth, int stringWidth)
       {
          return (int)((availableWidth - stringWidth) * digitAlignment);
       }
     
    	/*
    	 *  Determine the Y offset for the current row
    	 */
       private int getOffsetY(int rowStartOffset, FontMetrics fontMetrics)
       	throws BadLocationException
       {
       	//  Get the bounding rectangle of the row
     
          java.awt.Rectangle r = component.modelToView( rowStartOffset );
          int lineHeight = fontMetrics.getHeight();
          int y = r.y + r.height;
          int descent = 0;
     
       	//  The text needs to be positioned above the bottom of the bounding
       	//  rectangle based on the descent of the font(s) contained on the row.
     
          if (r.height == lineHeight)  // default font is being used
          {
             descent = fontMetrics.getDescent();
          }
          else  // We need to check all the attributes for font changes
          {
             if (fonts == null)
                fonts = new HashMap<String, FontMetrics>();
     
             Element root = component.getDocument().getDefaultRootElement();
             int index = root.getElementIndex( rowStartOffset );
             Element line = root.getElement( index );
     
             for (int i = 0; i < line.getElementCount(); i++)
             {
                Element child = line.getElement(i);
                AttributeSet as = child.getAttributes();
                String fontFamily = (String)as.getAttribute(StyleConstants.FontFamily);
                Integer fontSize = (Integer)as.getAttribute(StyleConstants.FontSize);
                String key = fontFamily + fontSize;
     
                FontMetrics fm = fonts.get( key );
     
                if (fm == null)
                {
                   Font font = new Font(fontFamily, Font.PLAIN, fontSize);
                   fm = component.getFontMetrics( font );
                   fonts.put(key, fm);
                }
     
                descent = Math.max(descent, fm.getDescent());
             }
          }
     
          return y - descent;
       }
     
    //
    //  Implement CaretListener interface
    //
       @Override
       public void caretUpdate(CaretEvent e)
       {
       	//  Get the line the caret is positioned on
     
          int caretPosition = component.getCaretPosition();
          Element root = component.getDocument().getDefaultRootElement();
          int currentLine = root.getElementIndex( caretPosition );
     
       	//  Need to repaint so the correct line number can be highlighted
     
          if (lastLine != currentLine)
          {
             repaint();
             lastLine = currentLine;
          }
       }
     
    //
    //  Implement DocumentListener interface
    //
       @Override
       public void changedUpdate(DocumentEvent e)
       {
          documentChanged();
       }
     
       @Override
       public void insertUpdate(DocumentEvent e)
       {
          documentChanged();
       }
     
       @Override
       public void removeUpdate(DocumentEvent e)
       {
          documentChanged();
       }
     
    	/*
    	 *  A document change may affect the number of displayed lines of text.
    	 *  Therefore the lines numbers will also change.
    	 */
       private void documentChanged()
       {
       	//  View of the component has not been updated at the time
       	//  the DocumentEvent is fired
     
          SwingUtilities.invokeLater(
                new Runnable()
                {
                   @Override
                   public void run()
                   {
                      try
                      {
                         int endPos = component.getDocument().getLength();
                         java.awt.Rectangle rect = component.modelToView(endPos);
     
                         if (rect != null && rect.y != lastHeight)
                         {
                            setPreferredWidth();
                            repaint();
                            lastHeight = rect.y;
                         }
                      }
                      catch (BadLocationException ex) { /* nothing to do */ }
                   }
                });
       }
     
    //
    //  Implement PropertyChangeListener interface
    //
       @Override
       public void propertyChange(PropertyChangeEvent evt)
       {
          if (evt.getNewValue() instanceof Font)
          {
             if (updateFont)
             {
                Font newFont = (Font) evt.getNewValue();
                setFont(newFont);
                lastDigits = 0;
                setPreferredWidth();
             }
             else
             {
                repaint();
             }
          }
       }
     
       public static void main(String[] args)
       {
     
     
          javax.swing.JFrame jf = new javax.swing.JFrame();
     
          jf.setVisible(true);
     
          JTextArea ta = new JTextArea(25, 25);
     
          javax.swing.JScrollPane sp = new javax.swing.JScrollPane(ta, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
     
     
          TextLineNumber tln = new TextLineNumber(ta);
          sp.setRowHeaderView( tln );
          jf.setContentPane(sp);
     
     
     
       }
    }
    Attached Images Attached Images
    JavaScript is NOT Java.

Similar Threads

  1. How to Change JTextArea font, font size and color
    By Flash in forum Java Swing Tutorials
    Replies: 7
    Last Post: January 14th, 2012, 10:47 PM
  2. Random numbers
    By Pooja Deshpande in forum Java SE APIs
    Replies: 8
    Last Post: June 5th, 2009, 05:36 AM
  3. Replies: 1
    Last Post: May 21st, 2009, 04:41 AM
  4. Reading a file line by line using the Scanner class
    By JavaPF in forum File Input/Output Tutorials
    Replies: 0
    Last Post: April 17th, 2009, 08:34 AM
  5. How to Read a file line by line using BufferedReader?
    By JavaPF in forum File Input/Output Tutorials
    Replies: 0
    Last Post: May 19th, 2008, 07:32 AM