javaswingjtextpanestyleddocument

Remove JTextPane Lines and Keep Styling


I'm using JTextPane and StyledDocument for styling message and I want to clear the messages or clear only the oldest message. I can easily clear all by using:

textPane.setText("");

But if I want to clear all, except some lines, then not sure if/how it can be done. I tried

textPane.setText(textPane.getText().substring(0, Math.min(200, textPane.getText().length())));

but the issue is that it remove the content styling.

Here is simple demo that shows the issue. Is there an easy way to do it?

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;

public class TestJTextPane {

    private JTextPane infoTextPane = new JTextPane();
    private StyledDocument styledDocument;
    private SimpleAttributeSet attributeSet = new SimpleAttributeSet();
    
    private JButton addText;
    private JButton clearText; 
    
    public static void main(String[] argv) {
        new TestJTextPane();
    }
    
    public TestJTextPane(){
        
        addText = new JButton("add");
        addText.addActionListener(new ActionListener() {
            
            @Override
            public void actionPerformed(ActionEvent e) {

                try {
                    StyleConstants.setForeground(attributeSet, Color.GREEN);
                    StyleConstants.setBackground(attributeSet, Color.BLACK);
                    StyleConstants.setBold(attributeSet, true);
                    StyleConstants.setFontSize(attributeSet, 20);
                    styledDocument.insertString(styledDocument.getLength(), "sample text message to add\n", attributeSet);
                    infoTextPane.setCaretPosition(infoTextPane.getDocument().getLength());
                } catch (BadLocationException e1) {
                    e1.printStackTrace();
                }
            }
        });
        
        clearText = new JButton("clear");
        clearText.addActionListener(new ActionListener() {
            
            @Override
            public void actionPerformed(ActionEvent e) {
                //infoTextPane.setText("");
                infoTextPane.setText(infoTextPane.getText().substring(0, Math.min(200, infoTextPane.getText().length())));
            }
        });
        
        styledDocument = infoTextPane.getStyledDocument();
        
        JPanel p = new JPanel();
        p.add(addText);
        p.add(clearText);
        p.add(infoTextPane);
        
        
        JFrame f = new JFrame("HyperlinkListener");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(p);
        f.setPreferredSize(new Dimension(400, 400));
        f.pack();
        f.setVisible(true);
    }
}

Solution

  • Figure how to do it with Element. For example, the below code will keep only the latest 2 messages.

    Element root = infoTextPane.getDocument().getDefaultRootElement();
    try {
        while(root.getElementCount() > 3){
            Element first = root.getElement(0);
            infoTextPane.getStyledDocument().remove(root.getStartOffset(), first.getEndOffset());
        }
    } catch (BadLocationException e1) {
        // FIXME Auto-generated catch block
        e1.printStackTrace();
    }