Search code examples
javaswingjtextareajtextpane

Problem with line number of JTextArea and resize JTextArea texts


this code count each line of JTextArea and add number of line in
left JTextPane

import java.awt.BorderLayout;
import java.awt.Color;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.border.MatteBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Element;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;

public class LineNumber extends JFrame implements DocumentListener {

    private static final long serialVersionUID = -1093726028044203117L;

    private JScrollPane scroll;
    private JTextArea textArea;
    private TextPane lineArea;

    public static void main(String[] args) {

        new LineNumber().setVisible(true);

    }

    public LineNumber() {

        super("Line Numbers");

        setSize(500, 500);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        setUI();
    }

    private void setUI() {

        textArea = new JTextArea();
        textArea.getDocument().addDocumentListener(this);

        lineArea = new TextPane(0, 3);
        lineArea.setText(getLine());

        lineArea.setEditable(false);
        lineArea.setFocusable(false);
        lineArea.setBorder(new MatteBorder(0, 0, 0, 1, new Color(248, 248, 248)));
        lineArea.setBackground(new Color(255, 255, 255));
        lineArea.setForeground(Color.GRAY);

        scroll = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

        scroll.setViewportView(textArea);
        scroll.setRowHeaderView(lineArea);
        getContentPane().add(scroll, BorderLayout.CENTER);

    }

    public void changedUpdate(DocumentEvent event) {

            lineArea.setText(getLine());

    }

    public void insertUpdate(DocumentEvent event) {

        lineArea.setText(getLine());
    }

    public void removeUpdate(DocumentEvent event) {


        lineArea.setText(getLine());

    }

    private String getLine() {

        int caretPos = 0;
        String lines = "";

        caretPos = textArea.getDocument().getLength();
        Element root = textArea.getDocument().getDefaultRootElement();

        for (int i = 1; i < root.getElementIndex(caretPos) + 2; i++)
            lines += String.format("%s  \n", i);

        return lines;

    }

    private int getLength() {

        int caretPos = 0;
        int length = 0;

        caretPos = textArea.getDocument().getLength();
        Element root = textArea.getDocument().getDefaultRootElement();

        int max = 0;
        for (int i = 1; i < root.getElementIndex(caretPos) + 2; i++)
            length = String.valueOf(Math.max(i, max)).length();

        return length;

    }


    private void setRightAlign() {

        StyledDocument doc = lineArea.getStyledDocument();
        SimpleAttributeSet right = new SimpleAttributeSet();

        StyleConstants.setAlignment(right, StyleConstants.ALIGN_RIGHT);
        doc.setParagraphAttributes(0, doc.getLength(), right, false);

    }

}

if lineArea and textArea use same font with same size
program work good but if change or resize font of textArea
it doesn't work well with different font sizes
and was ending too short of the actual end line

code work good and care balance with line number

afte change textarea font or font size :

enter image description here

after resize line area and textarea not balance
I do not want change size of textarea font
only nee balance textarea with line numbers


Solution

  • I don't know what the TextPane class is because that is not a standard JDK component.

    If it is a JTextArea, then maybe you can override the getRowHeight(..) method to return the height based on the Font of the main JTextArea.

    If it is a JTextPane, then maybe you can use the StyleConstants.setSpaceBelow(...) to add extra space after every line. So you would need to get the Font metrics of both Fonts that are being used to calculate the height of each Font. Then the difference would be the about you use for the space below method.

    The other option is to use the class I provided in your last question. It already support this functionality.