Pressing Ctrl+A is changing the Font in JTextPane

I am creating a simple Text editor using Java Swing with JTextPane component. I have added the code to make the text as Bold, Italics, Underline and also I have added code to get the system fonts in a JComboBox, so that I can change the font of the JTextPane content. And if the content has multiple font styles, it will display the corresponding font name according to the cursor position.

I have an issue: if the content has more than one font styles, pressing Ctrl+A is selecting all the content and also it is changing whole content font to the same font (which is the font style of the first line). Before pressing Ctrl+A:

Before pressing Ctrl+A

After pressing Ctrl+A, the first line’s font style – Calibri font is applied to all the three lines, below picture:

enter image description here

here is the simplest code

import java.awt.BorderLayout;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.rtf.RTFEditorKit;

public class Editor2 {
    private JTextPane editor;
    private DefaultStyledDocument doc;
    private DefaultComboBoxModel<String> fontFamilyComboBoxModel;
    private JComboBox<String> fontSizeComboBox;
    private JComboBox<String> fontFamilyComboBox;
    private AttributeSet attrs;
    private String fontFamilyStr;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new Editor2().createAndShowGUI();
            }
        });
    }

    private void createAndShowGUI() {
        editor = new JTextPane();
        editor.setMargin(new Insets(5, 5, 5, 5));
        RTFEditorKit rtf = new RTFEditorKit();
        editor.setEditorKit(rtf);
        editor.addCaretListener(new MyCaretListener());
        JScrollPane editorScrollPane = new JScrollPane(editor);
        doc = new DefaultStyledDocument();
        initDocAttrs();
        editor.setDocument(doc);
        final String[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
        fontFamilyComboBoxModel = new DefaultComboBoxModel<>(fonts);
        fontFamilyComboBox = new JComboBox<String>(fontFamilyComboBoxModel);
        fontFamilyComboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                String name = (String) fontFamilyComboBox.getSelectedItem();
                new StyledEditorKit.FontFamilyAction("font-family-" + name, name).actionPerformed(ae);
                editor.requestFocus();
            }
        });

        final String[] fontSizes = { "Font Size", "10", "11", "12", "14", "16", "18", "20", "24", "28", "30", "34",
                "40", "50" };
        fontSizeComboBox = new JComboBox<String>(fontSizes);
        fontSizeComboBox.setEditable(false);

        JFrame frame = new JFrame("Text Editor");
        frame.add(fontFamilyComboBox, BorderLayout.SOUTH);
        frame.add(fontSizeComboBox, BorderLayout.NORTH);
        frame.add(editorScrollPane, BorderLayout.CENTER);
        frame.add(editorScrollPane);
        frame.setSize(800, 400);
        frame.setLocation(300, 150);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        editor.requestFocusInWindow();
    }

    private void initDocAttrs() {
        Style style = doc.addStyle("my_doc_style", null);
        StyleConstants.setFontSize(style, 12);
        StyleConstants.setFontFamily(style, "Arial");
        doc.setParagraphAttributes(5, doc.getLength(), style, true);
    }

    private class MyCaretListener implements CaretListener {
        @Override
        public void caretUpdate(CaretEvent e) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    attrs = ((StyledEditorKit) editor.getEditorKit()).getInputAttributes();
                    System.out.println(attrs);
                    fontFamilyStr = (String) attrs.getAttribute(StyleConstants.FontFamily);
                    System.out.println("Font: " + fontFamilyStr);
                    fontFamilyComboBox.setSelectedItem(fontFamilyStr);
                }
            });
            System.out.println("---");
        }
    }
}

Why pressing Ctrl+A is changing all the font style? can anyone help me on this?

Answer

fontFamilyComboBox.setSelectedItem(fontFamilyStr);

In your CaretListener you are changing the selected item which results in the ActionListener for the combo box to be invoked, which causes you to change the font for the selected text.

One solution would be to remove the ActionListner from the combo box before changing the selected item:

comboBox.removeActionListener(...);
comboBox.setSelectedItem(fontFamilyStr);
comboBox.addActionListener(..)

Leave a Reply

Your email address will not be published. Required fields are marked *