You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java开发:如何为JTextArea添加语法高亮并修改指定单词颜色

实现Java代码编辑器的特定单词语法高亮

JTextArea本身仅支持单一格式文本,无法直接实现语法高亮。下面提供两种可行方案,帮你给特定单词设置颜色:

方案1:替换为JTextPane + StyledDocument

JTextPane支持富文本渲染,配合StyledDocument可以轻松给指定文本片段设置样式,是实现语法高亮的首选方案。

修改后的示例代码:

import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TextEditor extends JFrame {
    TextEditor(){
        JTextPane textPane;
        JScrollPane scrollPane;
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle("foo");
        this.setSize(1000,1000);
        this.setLayout(new FlowLayout());
        this.setLocationRelativeTo(null);
        
        textPane = new JTextPane();
        textPane.setLineWrap(true);
        textPane.setWrapStyleWord(true);
        textPane.setFont(new Font("Times New Roman", Font.PLAIN, 20));
        
        scrollPane = new JScrollPane(textPane);
        scrollPane.setPreferredSize(new Dimension(950,950));
        scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        
        this.add(scrollPane);
        this.setVisible(true);
        
        // 初始化语法高亮逻辑
        initSyntaxHighlight(textPane);
    }

    // 配置高亮样式和文本监听
    private void initSyntaxHighlight(JTextPane textPane) {
        StyledDocument doc = textPane.getStyledDocument();
        // 创建关键字高亮样式:蓝色加粗
        Style keywordStyle = textPane.addStyle("keywordStyle", null);
        StyleConstants.setForeground(keywordStyle, Color.BLUE);
        StyleConstants.setBold(keywordStyle, true);
        
        // 定义需要高亮的Java关键字列表
        String[] keywords = {"class", "public", "static", "void", "int", "String", "new", "if", "else"};
        
        // 监听文本变更,实时更新高亮
        textPane.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void insertUpdate(DocumentEvent e) {
                highlightKeywords(doc, keywords, keywordStyle, textPane);
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                highlightKeywords(doc, keywords, keywordStyle, textPane);
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                highlightKeywords(doc, keywords, keywordStyle, textPane);
            }
        });
        
        // 初始扫描一次文本
        highlightKeywords(doc, keywords, keywordStyle, textPane);
    }

    // 核心高亮逻辑:扫描文本并应用样式
    private void highlightKeywords(StyledDocument doc, String[] keywords, Style style, JTextPane textPane) {
        try {
            String text = doc.getText(0, doc.getLength());
            // 先清除所有旧样式,恢复默认格式
            doc.setCharacterAttributes(0, text.length(), textPane.getStyle("default"), true);
            
            // 遍历关键字,用正则匹配完整单词(避免部分匹配)
            for (String keyword : keywords) {
                Pattern pattern = Pattern.compile("\\b" + Pattern.quote(keyword) + "\\b");
                Matcher matcher = pattern.matcher(text);
                
                while (matcher.find()) {
                    int start = matcher.start();
                    int end = matcher.end();
                    doc.setCharacterAttributes(start, end - start, style, false);
                }
            }
        } catch (BadLocationException ex) {
            ex.printStackTrace();
        }
    }

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

方案2:给JTextArea自定义Highlighter

如果不想替换组件,可以通过JTextArea的Highlighter接口,自定义绘制器来给特定单词上色(仅支持背景色或通过自定义Painter修改前景色)。

示例代码:

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import java.awt.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TextEditor extends JFrame {
    TextEditor(){
        JTextArea textArea;
        JScrollPane scrollPane;
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle("foo");
        this.setSize(1000,1000);
        this.setLayout(new FlowLayout());
        this.setLocationRelativeTo(null);
        
        textArea = new JTextArea();
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        textArea.setFont(new Font("Times New Roman", Font.PLAIN, 20));
        
        scrollPane = new JScrollPane(textArea);
        scrollPane.setPreferredSize(new Dimension(950,950));
        scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        
        this.add(scrollPane);
        this.setVisible(true);
        
        // 设置高亮逻辑
        setupTextAreaHighlight(textArea);
    }

    private void setupTextAreaHighlight(JTextArea textArea) {
        // 创建蓝色前景色的高亮绘制器
        DefaultHighlighter.DefaultHighlightPainter keywordPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.BLUE) {
            @Override
            public void paint(Graphics g, int p0, int p1, Shape bounds, JTextComponent c) {
                // 重写绘制方法,修改文本前景色而非背景
                Graphics2D g2 = (Graphics2D) g;
                Color oldColor = g2.getColor();
                g2.setColor(getColor());
                g2.drawString(c.getText(p0, p1 - p0), bounds.getBounds().x, bounds.getBounds().y + c.getFontMetrics(c.getFont()).getAscent());
                g2.setColor(oldColor);
            }
        };
        
        // 监听文本变更
        textArea.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void insertUpdate(DocumentEvent e) {
                highlightTextAreaKeywords(textArea, keywordPainter);
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                highlightTextAreaKeywords(textArea, keywordPainter);
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                highlightTextAreaKeywords(textArea, keywordPainter);
            }
        });
        
        // 初始高亮
        highlightTextAreaKeywords(textArea, keywordPainter);
    }

    private void highlightTextAreaKeywords(JTextArea textArea, DefaultHighlighter.DefaultHighlightPainter painter) {
        textArea.getHighlighter().removeAllHighlights(); // 清除旧高亮
        String text = textArea.getText();
        String[] keywords = {"class", "public", "static", "void", "int", "String"};
        
        for (String keyword : keywords) {
            Pattern pattern = Pattern.compile("\\b" + Pattern.quote(keyword) + "\\b");
            Matcher matcher = pattern.matcher(text);
            
            while (matcher.find()) {
                try {
                    textArea.getHighlighter().addHighlight(matcher.start(), matcher.end(), painter);
                } catch (BadLocationException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

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

注意事项

  • 方案1的JTextPane支持更丰富的样式(如加粗、斜体),适合复杂语法高亮需求;
  • 正则中的\b用于匹配完整单词,避免误匹配(比如不会把String匹配到StringBuilder里的片段);
  • 实时监听文本变更在大文本场景下可能有性能问题,可优化为延迟扫描(比如用SwingUtilities.invokeLater或定时器)。

内容的提问来源于stack exchange,提问作者yavda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 23:40:31