How to change the color of specific words in a JTextPane?

前端 未结 4 1228
醉酒成梦
醉酒成梦 2020-11-28 07:54

How do I change the color of specific words in a JTextPane just while the user is typing? Should I override JTextPane paintComponent m

4条回答
  •  悲&欢浪女
    2020-11-28 08:21

    You can extend DefaultStyledDocument like I did here for an SQL editor I am building with keyword text coloring ...

        import java.util.ArrayList;
        import java.util.List;
        import javax.swing.text.AttributeSet;
        import javax.swing.text.BadLocationException;
        import javax.swing.text.DefaultStyledDocument;
        import javax.swing.text.Style;
    
        public class KeywordStyledDocument extends DefaultStyledDocument  {
            private static final long serialVersionUID = 1L;
            private Style _defaultStyle;
            private Style _cwStyle;
    
            public KeywordStyledDocument(Style defaultStyle, Style cwStyle) {
                _defaultStyle =  defaultStyle;
                _cwStyle = cwStyle;
            }
    
             public void insertString (int offset, String str, AttributeSet a) throws BadLocationException {
                 super.insertString(offset, str, a);
                 refreshDocument();
             }
    
             public void remove (int offs, int len) throws BadLocationException {
                 super.remove(offs, len);
                 refreshDocument();
             }
    
             private synchronized void refreshDocument() throws BadLocationException {
                 String text = getText(0, getLength());
                 final List list = processWords(text);
    
                 setCharacterAttributes(0, text.length(), _defaultStyle, true);   
                 for(HiliteWord word : list) {
                     int p0 = word._position;
                     setCharacterAttributes(p0, word._word.length(), _cwStyle, true);
                 }
             }       
    
             private static  List processWords(String content) {
                 content += " ";
                 List hiliteWords = new ArrayList();
                 int lastWhitespacePosition = 0;
                 String word = "";
                 char[] data = content.toCharArray();
    
                 for(int index=0; index < data.length; index++) {
                     char ch = data[index];
                     if(!(Character.isLetter(ch) || Character.isDigit(ch) || ch == '_')) {
                         lastWhitespacePosition = index;
                         if(word.length() > 0) {
                             if(isReservedWord(word)) {
                                 hiliteWords.add(new HiliteWord(word,(lastWhitespacePosition - word.length())));
                             }
                             word="";
                         }
                     }
                     else {
                         word += ch;
                     }
                }
                return hiliteWords;
             }
    
             private static final boolean isReservedWord(String word) {
                 return(word.toUpperCase().trim().equals("CROSS") || 
                                word.toUpperCase().trim().equals("CURRENT_DATE") ||
                                word.toUpperCase().trim().equals("CURRENT_TIME") ||
                                word.toUpperCase().trim().equals("CURRENT_TIMESTAMP") ||
                                word.toUpperCase().trim().equals("DISTINCT") ||
                                word.toUpperCase().trim().equals("EXCEPT") ||
                                word.toUpperCase().trim().equals("EXISTS") ||
                                word.toUpperCase().trim().equals("FALSE") ||
                                word.toUpperCase().trim().equals("FETCH") ||
                                word.toUpperCase().trim().equals("FOR") ||
                                word.toUpperCase().trim().equals("FROM") ||
                                word.toUpperCase().trim().equals("FULL") ||
                                word.toUpperCase().trim().equals("GROUP") ||
                                word.toUpperCase().trim().equals("HAVING") ||
                                word.toUpperCase().trim().equals("INNER") ||
                                word.toUpperCase().trim().equals("INTERSECT") ||
                                word.toUpperCase().trim().equals("IS") ||
                                word.toUpperCase().trim().equals("JOIN") ||
                                word.toUpperCase().trim().equals("LIKE") ||
                                word.toUpperCase().trim().equals("LIMIT") ||
                                word.toUpperCase().trim().equals("MINUS") ||
                                word.toUpperCase().trim().equals("NATURAL") ||
                                word.toUpperCase().trim().equals("NOT") ||
                                word.toUpperCase().trim().equals("NULL") ||
                                word.toUpperCase().trim().equals("OFFSET") ||
                                word.toUpperCase().trim().equals("ON") ||
                                word.toUpperCase().trim().equals("ORDER") ||
                                word.toUpperCase().trim().equals("PRIMARY") ||
                                word.toUpperCase().trim().equals("ROWNUM") ||
                                word.toUpperCase().trim().equals("SELECT") ||
                                word.toUpperCase().trim().equals("SYSDATE") ||
                                word.toUpperCase().trim().equals("SYSTIME") ||
                                word.toUpperCase().trim().equals("SYSTIMESTAMP") ||
                                word.toUpperCase().trim().equals("TODAY") ||
                                word.toUpperCase().trim().equals("TRUE") ||
                                word.toUpperCase().trim().equals("UNION") ||
                                word.toUpperCase().trim().equals("UNIQUE") ||
                                word.toUpperCase().trim().equals("WHERE"));
            }
        }
    

    Simply add it to your class like so:

        import java.awt.BorderLayout;
        import java.awt.Color;
        import java.awt.Font;
        import javax.swing.JFrame;
        import javax.swing.JScrollPane;
        import javax.swing.JTextPane;
        import javax.swing.text.BadLocationException;
        import javax.swing.text.Style;
        import javax.swing.text.StyleConstants;
        import javax.swing.text.StyleContext;
    
        public class SQLEditor extends JFrame {
            private static final long serialVersionUID = 1L;
    
            public SQLEditor() {
                StyleContext styleContext = new StyleContext();
                Style defaultStyle = styleContext.getStyle(StyleContext.DEFAULT_STYLE);
                Style cwStyle = styleContext.addStyle("ConstantWidth", null);
                StyleConstants.setForeground(cwStyle, Color.BLUE);
                StyleConstants.setBold(cwStyle, true);
    
                final JTextPane pane = new JTextPane(new KeywordStyledDocument(defaultStyle, cwStyle));
                pane.setFont(new Font("Courier New", Font.PLAIN, 12));
    
                JScrollPane scrollPane = new JScrollPane(pane);
                getContentPane().add(scrollPane, BorderLayout.CENTER);
                setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                setSize(375, 400);      
            }
    
            public static void main(String[] args) throws BadLocationException {
                SQLEditor app = new SQLEditor();
                app.setVisible(true);
            }
        }
    

    Here's the missing HiliteWord class ...

    public class HiliteWord {
    
        int _position;  
        String _word;
    
        public HiliteWord(String word, int position) {
            _position = position;   
            _word = word;
        }
    }
    

提交回复
热议问题