要实现高亮效果,我们需要把JEditorPane默认的编辑工具类覆盖掉。我们自己实现自己的编辑工具类。

在swing中,已经有一些工具类的子类,我们直接继承该子类就行了,我们继承StyledEditorKit类。
如下:

public class JavaCodeEditor extends StyledEditorKit{

	@Override
	public Document createDefaultDocument() {
		return super.createDefaultDocument();
	}

	@Override
	public ViewFactory getViewFactory() {
		return new JavaViewFactory();
	}

}

上面这段代码,我们主要关注getViewFactory方法。这个方法返回一个试图工厂类,我们就是在这个工厂类中处理我们的文本内容。
代码如下:

public class JavaViewFactory implements ViewFactory{

	@Override
	public View create(Element elem) {
		return new XmlView(elem);
	}

}

这个类有一个创建工厂的方法,是未实现的,我们自己定义一个类实现View接口然后返回。

View接口以及有很多实现子类,我们选择继承PlainView即可。
代码如下:

import java.awt.Color;
import java.awt.Graphics;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.PlainDocument;
import javax.swing.text.PlainView;
import javax.swing.text.Segment;
import javax.swing.text.Utilities;

public class XmlView extends PlainView {

    private static HashMap<Pattern, Color> patternColors;
    private static String TAG_PATTERN = "(</?[A-Za-z\\-_0-9]*)\\s?>?";
    private static String TAG_ATTRIBUTE_PATTERN = "\\s(\\w*)\\=";
    private static String TAG_ATTRIBUTE_VALUE = "[a-z\\-]*\\=(\"[^\"]*\")";
    private static String TAG_COMMENT = "(<\\!--[^-]*+(?>-(?!->))*+-->)";
    private static String TAG_COMMENT_JAVA = "(/\\*\\*\\s+[\\u4e00-\\u9fa5]+:[\\w\\d\\(\\),]+\\s+\\*/)";
    private static String TAG_CDATA = "(<\\!\\[CDATA\\[)";
    private static String TAG_CDATA_END = "(\\]\\]>)";
    private static String TAG_JAVA = "(public|private|return)";
    

    static {
        // NOTE: the order is important!
        patternColors = new LinkedHashMap<Pattern, Color>();
        patternColors.put(Pattern.compile(TAG_PATTERN), new Color(0, 0, 128));
        patternColors.put(Pattern.compile(TAG_CDATA), Color.GRAY);
        patternColors.put(Pattern.compile(TAG_CDATA_END), Color.GRAY);
        patternColors.put(Pattern.compile(TAG_ATTRIBUTE_PATTERN), new Color(40, 0, 252));
        patternColors.put(Pattern.compile(TAG_ATTRIBUTE_VALUE), new Color(43, 128, 0));
        patternColors.put(Pattern.compile(TAG_COMMENT), new Color(0, 128, 0));
        patternColors.put(Pattern.compile(TAG_COMMENT_JAVA), new Color(0, 128, 0));
        patternColors.put(Pattern.compile(TAG_JAVA), new Color(127,0,85));
    }

    public XmlView(Element element) {

        super(element);
        getDocument().putProperty(PlainDocument.tabSizeAttribute, 4);
    }

    @Override
    protected int drawUnselectedText(Graphics graphics, int x, int y, int p0,
            int p1) throws BadLocationException {

        Document doc = getDocument();
        String text = doc.getText(p0, p1 - p0);

        Segment segment = getLineBuffer();

        SortedMap<Integer, Integer> startMap = new TreeMap<Integer, Integer>();
        SortedMap<Integer, Color> colorMap = new TreeMap<Integer, Color>();
        
        for (Map.Entry<Pattern, Color> entry : patternColors.entrySet()) {

            Matcher matcher = entry.getKey().matcher(text);

            while (matcher.find()) {
                startMap.put(matcher.start(1), matcher.end());
                colorMap.put(matcher.start(1), entry.getValue());
            }
        }
        int i = 0;

        for (Map.Entry<Integer, Integer> entry : startMap.entrySet()) {
            int start = entry.getKey();
            int end = entry.getValue();

            if (i < start) {
                graphics.setColor(Color.black);
                doc.getText(p0 + i, start - i, segment);
                x = Utilities.drawTabbedText(segment, x, y, graphics, this, i);
            }

            graphics.setColor(colorMap.get(start));
            i = end;
            doc.getText(p0 + start, i - start, segment);
            x = Utilities.drawTabbedText(segment, x, y, graphics, this, start);
        }
        if (i < text.length()) {
            graphics.setColor(Color.black);
            doc.getText(p0 + i, text.length() - i, segment);
            x = Utilities.drawTabbedText(segment, x, y, graphics, this, i);
        }

        return x;
    }

}

上面代码的大意就是:定义需要高亮代码的正则表达式,然后把表达式和颜色一起放入Map中。PlainView中的drawUnselectedText方法会逐行渲染JEditorPane的内容。

第一个for循环就是循环 表达式的Map,用表达式来找当前行里符合内容的关键字,并把起始位置保存到startMap 中,同时把颜色也存入colorMap 中,key就是符合表达式的字符的index。

第二个for循环是循环startMap,根据起始的坐标,获取colorMap 中的颜色,然后渲染文本。

如果 i 的位置小于 第一个匹配成功的字符串位置,那么从i的位置到第一匹配成功的位置设置颜色为黑色,同理,如果把所有匹配的字符串都已经设置颜色,i的位置任然没有到达本行字符串结尾,那么就把i的位置到text.length之间的内容设置为黑色。

上面三个类创建完成就可以进行测试了。

创建一个JFrame来测试,代码如下:

import javax.swing.JEditorPane;
import javax.swing.JFrame;

public class MyFrame extends JFrame{

	private JEditorPane editorPane;

	public MyFrame (){
		editorPane = new JEditorPane();
		editorPane.setBounds(0, 0, 1000, 600);
		editorPane.setEditorKit(new JavaCodeEditor());
		editorPane.setText( "\n<update id=\"update\" parameterClass=\"map\">\n"+
	            "\tupdate tableName a  \n"+
	            "\t\t<dynamic prepend=\"SET\">\n"+
	            "\t \t\t\t<isPropertyAvailable prepend=\",\" property=\"desc\">   <!--\t命令获得:tableName\t-->\n"+
	            "\t\t\t\ta.desc = #desc# \n"+
	            "\t\t\t</isPropertyAvailable>\n"+
	            "\t\t\t<isPropertyAvailable prepend=\",\" property=\"aac001\">   <!--\t人员ID:VARCHAR2(20)\t-->\n"+
	            "\t\t\t\ta.aac001 = #aac001# \n"+
	            "\t\t\t</isPropertyAvailable>\n"+
	            "\t\t\t<isPropertyAvailable prepend=\",\" property=\"aac003\">   <!--\t姓名:VARCHAR2(60)\t-->\n"+
	            "\t\t\t\ta.aac003 = #aac003# \n"+
	            "\t\t\t</isPropertyAvailable>\n"+
	            "\t\t\t<isPropertyAvailable prepend=\",\" property=\"aac004\">   <!--\t性别:VARCHAR2(6)\t-->\n"+
	            "\t\t\t\ta.aac004 = #aac004# \n"+
	            "\t\t\t</isPropertyAvailable>\n"+
	            "\t\t\t<isPropertyAvailable prepend=\",\" property=\"aac005\">   <!--\t民族:VARCHAR2(6)\t-->\n"+
	            "\t\t\t\ta.aac005 = #aac005# \n"+
	            "\t\t\t</isPropertyAvailable>\n"+
	            "\t\t\t<isPropertyAvailable prepend=\",\" property=\"aac006\">   <!--\t出生日期:DATE\t-->\n"+
	            "\t\t\t\ta.aac006 = #aac006# \n"+
	            "\t\t\t</isPropertyAvailable>\n"+
	            "\t\t\t<isPropertyAvailable prepend=\",\" property=\"aaf039\">   <!--\t工资:NUMBER(14,2)\t-->\n"+
	            "\t\t\t\ta.aaf039 = #aaf039# \n"+
	            "\t\t\t</isPropertyAvailable>\n"+
	            "\t\t</dynamic>\n"+
	            "\twhere a.index = #index#\n"+
	            "</update>\n"+
	            "/**   工资:NUMBER(14,2) */\n"+
	            "private BigDecimal aaf039;\n"+
	            "<![CDATA[	   AND aae001 = #aae001#    ]]>");
		
		add(editorPane);
		setSize(1000,600);
		setLocationRelativeTo(null);
		setVisible(true);
		
	}
	
	public static void main(String[] args) {
		new MyFrame ();
	}
}

代码有一行:editorPane.setEditorKit(new JavaCodeEditor()); 这里把我们自己创建的编辑器替换editorPane默认的编辑器。

运行效果如下:

java 文字高亮 java实现代码高亮_java


这里最关键的地方就是正则表达式了,所以正则表达式一定要过关。get到的小伙伴给个点赞吧