Making JLable in JTextPane Undeletable

106 views Asked by At

I currently have a JLabel embedded in a JTextPane using this:

import javax.swing.*;
import javax.swing.text.*;

public class MainFrame
{
    JFrame mainFrame = new JFrame("Main Frame");
    JTextPane textPane = new JTextPane();

    public MainFrame()
    {
        String[] components = {"Title", "\n"};
        String[] styles = {"LABEL_ALIGN", "LEFT_ALIGN"};

        StyledDocument sd = textPane.getStyledDocument();
        Style DEFAULT_STYLE = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);

        Style LEFT_STYLE = sd.addStyle("LEFT_ALIGN", DEFAULT_STYLE);
        StyleConstants.setAlignment(LEFT_STYLE, StyleConstants.ALIGN_LEFT);

        Style CENTER_STYLE = sd.addStyle("CENTER_ALIGN", DEFAULT_STYLE);
        StyleConstants.setAlignment(CENTER_STYLE, StyleConstants.ALIGN_CENTER);

        JLabel titleLbl = new JLabel("Title");
        Style LABEL_STYLE = sd.addStyle("LABEL_ALIGN", DEFAULT_STYLE);
        StyleConstants.setAlignment(LABEL_STYLE, StyleConstants.ALIGN_CENTER);
        StyleConstants.setComponent(LABEL_STYLE, titleLbl);

        for(int i = 0; i < components.length; i++)
        {
            try
            {
                sd.insertString(sd.getLength(), components[i], sd.getStyle(styles[i]));
                sd.setLogicalStyle(sd.getLength(), sd.getStyle(styles[i]));
            }
            catch(BadLocationException e)
            {
                e.printStackTrace();
            }
        }

        mainFrame.add(textPane);
        mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        mainFrame.pack();
        mainFrame.setVisible(true);
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(MainFrame::new);
    }
}

How can I make the label un-deletable? Because whenever I hold backspace, the label ends up getting removed from the JTextPane

2

There are 2 answers

0
camickr On BEST ANSWER

You might be able to use a NavigationFilter to prevent the removal of the component at the beginning of the text pane. Check out: How to make part of a JTextField uneditable for an example of this approach. In this case the label represents a single character so the prefix length would be set to 1. Or maybe you can just use the prefix concept itself and don't even use the JLabel.

Otherwise, you might be able to create a custom DocumentFilter. Check out the section from the Swing tutorial on Implementing a DocumentFilter for the basics.

So you would need to track the offset off the location of the component. Then in the remove(...) method of the filter you would need to check if you are removing data in the range of your offset. If so you would ignore the remove.

Of course the offset can dynamically change if you add or remove text before the label so you would need to manage that as well.

Or you can check out the Protected Text Component which attempts to manage all of that for you.

2
Jeremy Barnes On

Why not just put your title label outside the text area? That seems more intuitive.

It looks like there's no real way to avoid this while still allowing the textarea to be editable. You could place the label above the text frame so that it occupies the same space, or above the text frame so that it behaves like a proper title.

Unfortunately, the nature of the textarea is that all of its subcomponents are editable or none of them are.