首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JTextPane 語法高亮實戰:基於 DefaultStyledDocument 的 SQL 分析器實現

     編輯:Java 相關知識

JTextArea 無法滿足關鍵字著色、語法高亮等富文本需求,JTextPane 配合 DefaultStyledDocument 成為最佳選擇。本文源自實際 SQL 查詢分析器開發經驗,完整展示如何通過繼承 DefaultStyledDocument 實現實時語法高亮,支持多種數據庫方言的關鍵字識別與著色。

核心架構設計

JDAStyledDocument 繼承 DefaultStyledDocument,重寫插入/刪除方法,在文檔變更時觸發語法分析與屬性應用:


public class JDAStyledDocument extends DefaultStyledDocument {
    private int dbType = -1; // 數據庫類型:Oracle/MySQL/SQLServer 等
    private AttributeSet currentAttrSet = null;

    public JDAStyledDocument(int dbType) {
        this.dbType = dbType;
    }

    // 插入文本時觸發語法著色
    @Override
    public void insertString(int offset, String str, AttributeSet a) 
            throws BadLocationException {
        this.currentAttrSet = a;
        super.insertString(offset, str, a);
        setSyntaxColor(offset, str.length());
    }

    // 刪除文本後重新著色受影響區域
    @Override
    public void remove(int offs, int len) throws BadLocationException {
        super.remove(offs, len);
        setSyntaxColor(offs);
    }
    // ... 核心著色邏輯見下文
}

智能語法著色算法

採用「以光標位置為中心,雙向擴展至單詞邊界」的策略,精確別關鍵字:


// 核心著色入口:處理指定範圍內的語法高亮
private int setSyntaxColor(int offset, int len) throws BadLocationException {
    if (offset < 0 || len < 0) return offset;
    int tmpOffset = offset;
    while (tmpOffset < offset + len) {
        tmpOffset = setSyntaxColor(tmpOffset);      // 單詞級著色
        tmpOffset = getNextWordOffset(tmpOffset);   // 跳過空白字符
    }
    return setSyntaxColor(tmpOffset); // 處理最後一個單詞
}

// 單詞級著色:向前向後查找單詞邊界
private int setSyntaxColor(int offset) {
    if (offset < 0 || currentAttrSet == null) return offset;
    
    String before = getBeforeBlankString(offset - 1); // 向前找空格
    String after = getAfterBlankString(offset);       // 向後找空格
    String syntax = (before + after).trim();          // 完整單詞
    
    int start = offset - before.length();
    if (start < 0 || syntax.isEmpty()) return offset;

    // 關鍵字判斷與顏色應用
    Color color = SyntaxMgr.isSyntax(dbType, syntax);
    StyleConstants.setForeground((MutableAttributeSet) currentAttrSet, color);
    setCharacterAttributes(start, syntax.length(), currentAttrSet, true);
    return start + syntax.length();
}

// 獲取下一個單詞起始位置(跳過空白字符並著色)
private int getNextWordOffset(int offset) {
    int rOffset = offset;
    int length = getLength();
    while (rOffset <= length && rOffset >= 0) {
        String ch = getPositionChar(rOffset);
        if (!SyntaxMgr.isSpaceChar(ch)) break;
        rOffset++;
    }
    // 空白區域著色
    if (rOffset != offset) {
        StyleConstants.setForeground((MutableAttributeSet) currentAttrSet, 
            SyntaxColorMgr.getSpaceColor());
        setCharacterAttributes(offset, rOffset - offset, currentAttrSet, true);
    }
    return rOffset;
}

關鍵字管理與顏色策略

通過 SyntaxMgr 統一管理不同數據庫方言的關鍵字與顏色映射:


// 使用示例:根據數據庫類型創建文檔
JTextPane sqlPane = new JTextPane(new JDAStyledDocument(DBType.ORACLE));
// 或
JTextPane sqlPane = new JTextPane(new JDAStyledDocument(DBType.MYSQL));

關鍵技術點總結

  1. 增量著色:僅重新分析變更區域,避免全文檔掃描,保證大文件響應性能
  2. 邊界精確識別:雙向擴展算法準確處理單詞邊界,支持標識符、操作符、字符串字面量區分
  3. 屬性集復用:通過 MutableAttributeSet 復用樣式對象,減少內存分配
  4. 異步優化建議:大文件場景下可引入 SwingWorker 異步執行語法分析,避免阻塞 EDT

擴展方向

  • 集成 ANTLR 實現完整 SQL 解析器,支持語法錯誤提示
  • 添加代碼折疊、括號匹配、自動補全功能
  • 支持主題切換(暗色/亮色模式)通過樣式表動態替換
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved