AbiSaran
AbiSaran

Reputation: 2678

How to change the corresponding font name in JCombobox while placing the cursor or selecting the text in JTextPane?

I am creating a text editor application in Java Swing. I am using JTextPane and I have added code to get all the system fonts and some font sizes in JComboBox.

I have entered the text - "Hello World" in jtextpane and change the font of the words "Hello" to "Arial", font size to 10 and "World" to "Calibri", font size to 12.

My expected scenario: If I select the word "Hello" or place the cursor in the word "Hello", the font name in the font JCombobox should be changed automatically to "Arial" and font size Jcombobox should be automatically changed to 10, as same as for the word "World", the values in the Jcombobox should be changed to "Calibri" and "12". How can I achieve this? Thanks in advance.

Upvotes: 0

Views: 149

Answers (1)

prasad_
prasad_

Reputation: 14287

This basically addresses the issue how to select the combo box item corresponding to the selected text or the cursor position in text. For the example, I have chosen only the font size. The same technique can be applied to the font family also.

The example is a text editor using JTextPane and its document type is a DefaultStyledDocument. There is a JComboBox with a list of font sizes (16 to 50). One can select a section of text in the editor and select a font size from combo box to set the text to that font size. This is achieved using an ItemListener added to the JComboBox. The listener has code to set the editor document's attributes to the newly selected font size - to the selected text.

The editor allows multiple font sizes applied to different parts of the text as in the below picture.

enter image description here


The requirement was when the caret (or cursor) is placed in the text or a portion of selected text - the corresponding font size need to be set in the JComboBox with the font sizes. For this a CaretListener is added to the JTextPane.

This listener's logic mainly locates the caret position, gets the attributes of the document text at that position and extracts the font size attribute. This font size from this attribute is set in the font size combo box.

The example's code:

public class Editor2 {

    private JTextPane editor;
    private DefaultStyledDocument doc;
    private JComboBox<String> fontSizeComboBox;
    private boolean caretControlFlag;
    private static final int DEFAULT_FONT_SIZE = 18;

    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));
        editor.addCaretListener(new MyCaretListener());     
        JScrollPane editorScrollPane = new JScrollPane(editor);
        doc = new DefaultStyledDocument();
        initDocAttrs();
        editor.setDocument(doc);

        final String [] fontSizes = {"Font Size", "16", "18", 
            "20", "24", "28", "30", "34", "40", "50"};
        fontSizeComboBox = new JComboBox<String>(fontSizes);
        fontSizeComboBox.setEditable(false);
        fontSizeComboBox.addItemListener(new FontSizeItemListener());
        JFrame frame = new JFrame("Text Editor");
        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, 18);
        StyleConstants.setFontFamily(style, "SansSerif");
        doc.setParagraphAttributes(0, doc.getLength(), style, true);
    }

    private class FontSizeItemListener implements ItemListener {
        @Override
        public void itemStateChanged(ItemEvent e) {
            if ((e.getStateChange() != ItemEvent.SELECTED) ||
                    (fontSizeComboBox.getSelectedIndex() == 0)) {
                return;
            }
            String fontSizeStr = (String) e.getItem();
            int newFontSize = 0;
            try {
                newFontSize = Integer.parseInt(fontSizeStr);
            }
            catch (NumberFormatException ex) {
                return;
            }
            if (caretControlFlag) {
                caretControlFlag = false;
                return;
            }
            setFontAttrs(newFontSize);
            editor.requestFocusInWindow();
        }

        private void setFontAttrs(int newFontSize) {
            SimpleAttributeSet attrs = new SimpleAttributeSet();
            Style docStyle = doc.getStyle("my_doc_style");  
            int size = StyleConstants.getFontSize(docStyle);
            StyleConstants.setFontSize(attrs, newFontSize);
            String attrName = "mysize" + Integer.toString(newFontSize);
            attrs.addAttribute(attrName, attrName);

            int startPos = editor.getSelectionStart();
            String selectedText = editor.getSelectedText();
            if (selectedText == null || selectedText.trim().isEmpty()) {
                return;
            }
            int length = selectedText.length(); 
            doc.setCharacterAttributes(startPos, length, attrs, false);     
            editor.setDocument(doc);
        }
    }


    private class MyCaretListener implements CaretListener {
        @Override
        public void caretUpdate(CaretEvent e) {
            caretControlFlag = true;
            int dot = e.getDot();
            Element ele = doc.getCharacterElement(dot);
            AttributeSet attrs = ele.getAttributes();
            String fontSizeStr = "18";
            for (Enumeration en = attrs.getAttributeNames(); en.hasMoreElements();) {
                String attrName = en.nextElement().toString();
                if (attrName.contains("mysize")) {
                    fontSizeStr = attrName.substring(6);
                }
            }
            fontSizeComboBox.setSelectedItem(fontSizeStr);
            caretControlFlag = false;
        }
    }
}

Upvotes: 1

Related Questions