
Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
How can we display the line numbers inside a JTextArea in Java?
In this article, we will learn to display the line numbers inside a JTextArea in Java. When using text editors or code viewers in Java Swing applications, the showing of line numbers can greatly improve the user experience.
What is a JTextArea?
A JTextArea is a subclass of JTextComponent and it is a multi-line text component to display the text or allow the user to enter a text. A JTextArea can generate a CaretListener interface, which can listen to caret update events.
Syntax
The following is the syntax for JTextArea initialization:
JTextArea textArea = new JTextArea();
By default, JTextArea does not display the line numbers, we have to customize the code by using a DocumentListener interface.
Different Approaches
Using an Adjacent JTextArea
This approach uses a secondary JTextArea component to display line numbers alongside the main text area. Line numbers are held as text material in this nearby component, and they are kept in sync with the primary text area using document listeners.
Approach
The following are the steps to display the line numbers inside a JTextArea in Java:
- Create two JTextAreas - one for content and one for line numbers.
- Make the line number area read-only and have a different background.
- Attach a DocumentListener to the main textarea, and upon document changes, rerun all line numbers.
- Modify the line number JTextArea content.
- Put the main text area within the viewport, and line numbers in the row header.
- The line numbers scroll synchronously with the main content.
Example
Below is an example to display the line numbers inside a JTextArea in Java:
import java.awt.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.Element; public class LineNumberTextAreaTest extends JFrame { private static JTextArea textArea; private static JTextArea lines; private JScrollPane jsp; public LineNumberTextAreaTest() { setTitle("LineNumberTextArea Test"); jsp = new JScrollPane(); textArea = new JTextArea(); lines = new JTextArea("1"); lines.setBackground(Color.LIGHT_GRAY); lines.setEditable(false); // Code to implement line numbers inside the JTextArea textArea.getDocument().addDocumentListener(new DocumentListener() { public String getText() { int caretPosition = textArea.getDocument().getLength(); Element root = textArea.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(textArea); jsp.setRowHeaderView(lines); add(jsp); setSize(400, 275); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); setVisible(true); } public static void main(String[] args) { new LineNumberTextAreaTest(); } }
Output
Using a Custom JComponent
This approach creates a custom lightweight JComponent that paints line numbers directly onto its surface. It's more efficient as it only draws the visible line numbers and handles dynamic width adjustment.
Approach
The following are the steps to display the line numbers inside a JTextArea using a custom JComponent:
- Implement a custom subclass of JComponent for line numbers.
-
Override paintComponent() to cope with custom drawing.
- Compute the visible line range from the clip bounds, and compute the needed width from the number of lines.
- Add DocumentListener to trigger repaints on changes.
- Place the main text area in the viewport, and line numbers in the row header.
- The component repaints automatically upon being scrolled.
Example
Below is an example to display the line numbers inside a JTextArea using a custom JComponent:
import java.awt.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.Element; public class LineNumberTextAreaTest extends JFrame { private JTextArea textArea; private JComponent lineNumbers; private JScrollPane jsp; public LineNumberTextAreaTest() { setTitle("LineNumberTextArea Test"); jsp = new JScrollPane(); textArea = new JTextArea(); lineNumbers = new JComponent() { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); try { Element root = textArea.getDocument().getDefaultRootElement(); int lineCount = root.getElementCount(); int digits = String.valueOf(lineCount).length(); setPreferredSize(new Dimension(20 + digits * 8, 0)); g.setColor(Color.LIGHT_GRAY); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(Color.BLACK); FontMetrics fm = g.getFontMetrics(); int lineHeight = textArea.getFontMetrics(textArea.getFont()).getHeight(); Rectangle clip = g.getClipBounds(); int startY = clip.y; int endY = clip.y + clip.height; int startLine = startY / lineHeight; int endLine = Math.min(lineCount, startLine + (endY / lineHeight) + 1); for (int i = startLine; i < endLine; i++) { String num = Integer.toString(i + 1); int y = (i * lineHeight) + fm.getAscent(); g.drawString(num, getWidth() - fm.stringWidth(num) - 3, y); } } catch (Exception e) { e.printStackTrace(); } } }; lineNumbers.setFont(textArea.getFont()); textArea.getDocument().addDocumentListener(new DocumentListener() { @Override public void changedUpdate(DocumentEvent e) { lineNumbers.repaint(); } @Override public void insertUpdate(DocumentEvent e) { lineNumbers.repaint(); } @Override public void removeUpdate(DocumentEvent e) { lineNumbers.repaint(); } }); jsp.getViewport().add(textArea); jsp.setRowHeaderView(lineNumbers); add(jsp); setSize(400, 275); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); setVisible(true); } public static void main(String[] args) { new LineNumberTextAreaTest(); } }