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
相关产品推荐
相关产品推荐

