如何更改JTextPane中特定单词的颜色?

2022-09-01 13:48:13

如何在用户键入时更改特定单词的颜色?我应该重写方法吗?JTextPaneJTextPanepaintComponent


答案 1

不。你不应该重写 paintComponent() 方法。相反,您应该使用 。你也应该自己来界定这些词。StyledDocument

下面是演示,它在键入时将“公共”,“受保护”和“私有”变为红色,就像一个简单的代码编辑器一样:

enter image description here

import javax.swing.*;
import java.awt.*;
import javax.swing.text.*;

public class Test extends JFrame {
    private int findLastNonWordChar (String text, int index) {
        while (--index >= 0) {
            if (String.valueOf(text.charAt(index)).matches("\\W")) {
                break;
            }
        }
        return index;
    }

    private int findFirstNonWordChar (String text, int index) {
        while (index < text.length()) {
            if (String.valueOf(text.charAt(index)).matches("\\W")) {
                break;
            }
            index++;
        }
        return index;
    }

    public Test () {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(400, 400);
        setLocationRelativeTo(null);

        final StyleContext cont = StyleContext.getDefaultStyleContext();
        final AttributeSet attr = cont.addAttribute(cont.getEmptySet(), StyleConstants.Foreground, Color.RED);
        final AttributeSet attrBlack = cont.addAttribute(cont.getEmptySet(), StyleConstants.Foreground, Color.BLACK);
        DefaultStyledDocument doc = new DefaultStyledDocument() {
            public void insertString (int offset, String str, AttributeSet a) throws BadLocationException {
                super.insertString(offset, str, a);

                String text = getText(0, getLength());
                int before = findLastNonWordChar(text, offset);
                if (before < 0) before = 0;
                int after = findFirstNonWordChar(text, offset + str.length());
                int wordL = before;
                int wordR = before;

                while (wordR <= after) {
                    if (wordR == after || String.valueOf(text.charAt(wordR)).matches("\\W")) {
                        if (text.substring(wordL, wordR).matches("(\\W)*(private|public|protected)"))
                            setCharacterAttributes(wordL, wordR - wordL, attr, false);
                        else
                            setCharacterAttributes(wordL, wordR - wordL, attrBlack, false);
                        wordL = wordR;
                    }
                    wordR++;
                }
            }

            public void remove (int offs, int len) throws BadLocationException {
                super.remove(offs, len);

                String text = getText(0, getLength());
                int before = findLastNonWordChar(text, offs);
                if (before < 0) before = 0;
                int after = findFirstNonWordChar(text, offs);

                if (text.substring(before, after).matches("(\\W)*(private|public|protected)")) {
                    setCharacterAttributes(before, after - before, attr, false);
                } else {
                    setCharacterAttributes(before, after - before, attrBlack, false);
                }
            }
        };
        JTextPane txt = new JTextPane(doc);
        txt.setText("public class Hi {}");
        add(new JScrollPane(txt));
        setVisible(true);
    }

    public static void main (String args[]) {
        new Test();
    }
}

代码不是那么漂亮,因为我快速键入它,但它可以工作。我希望它能给你一些提示。


答案 2

覆盖不会对您有所帮助。paintComponent

这并不容易,但也并非不可能。像这样的东西将帮助你:

DefaultStyledDocument document = new DefaultStyledDocument();
JTextPane textpane = new JTextPane(document);
StyleContext context = new StyleContext();
// build a style
Style style = context.addStyle("test", null);
// set some style properties
StyleConstants.setForeground(style, Color.BLUE);
// add some data to the document
document.insertString(0, "", style);

您可能需要对此进行调整,但至少它显示了从哪里开始。


推荐