從寫JTextPane元件 實現關鍵字高亮顯示
package my2;
import java.util.StringTokenizer;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.rtf.RTFEditorKit;
/**
* 關鍵字特殊處理面板
* @author Administrator
*
*/
public class MyTextPane extends JTextPane {
/**
*
*/
private static final long serialVersionUID = -66377652770879651L;
protected StyleContext m_context;
protected DefaultStyledDocument m_doc;
private MutableAttributeSet keyAttr, normalAttr;
private MutableAttributeSet bracketAttr;
private MutableAttributeSet inputAttributes = new RTFEditorKit()
.getInputAttributes();
/**
* 所有關鍵字
*/
private final static String[] _keys = new String[] { "select", "from",
"where", "like", "and", "or", "order", "group", "sum", "avg",
"not", "in", "create", "grand", "null", "count", "max", "min",
"start", "with", "connect", "update", "delete", "set", "values",
"view", "table", "as", "distinct", "into", "drop", "is", "on",
"exists", "by", "tree", "table", "cust", "union", "dual",
"trigger", "function", "procedure", "begin", "end", "for", "loop",
"while", "insert", "count", "if", "else", "then", "commit",
"rollback", "return", "declare", "when", "elsif", "open", "fetch",
"close", "exit", "exception", "execute" };
/**
* 所與排除字符集
*/
private final static char[] _character = new char[] { '(', ')', ',', ';',
':', '\t', '\n', '+', '-', '*', '/' };
/**
* 初始化,包括關鍵字顏色,和非關鍵字顏色
*/
public MyTextPane() {
super();
m_context = new StyleContext();
m_doc = new DefaultStyledDocument(m_context);
this.setDocument(m_doc);
this.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent ke) {
dealSingleRow();
}
});
// 義關鍵字顯示屬性
keyAttr = new SimpleAttributeSet();
StyleConstants.setForeground(keyAttr, Color.RED);
// 義一般文字顯示屬性
normalAttr = new SimpleAttributeSet();
// StyleConstants.setFontFamily(normalAttr, "serif");
StyleConstants.setBold(normalAttr, false);
StyleConstants.setForeground(normalAttr, Color.black);
bracketAttr = new SimpleAttributeSet();
StyleConstants.setForeground(bracketAttr, Color.RED);
// StyleConstants.setFontFamily(bracketAttr, "serif");
StyleConstants.setBold(bracketAttr, true);
}
/**
* 設定大括號顏色
* @param _text
*/
private void setBracketColor(String _text) {
int len = _text.length();
for (int i = 0; i < len; i++) {
char ch = _text.charAt(i);
if (ch == '{' || ch == '}') {
m_doc.setCharacterAttributes(i, 1, bracketAttr, false);
}
}
}
/**
* 判斷字元是不是在排除字元行列
* @param _ch
* @return
*/
private boolean isCharacter(char _ch) {
for (int i = 0; i < _character.length; i++) {
if (_ch == _character[i]) {
return true;
}
}
return false;
}
/**
* 設定關鍵字顏色
* @param _key
* @param _start
* @param _length
* @return
*/
private int setKeyColor(String _key, int _start, int _length) {
for (int i = 0; i < _keys.length; i++) {
int li_index = _key.indexOf(_keys[i]);
if (li_index < 0) {
continue;
}
int li_legnth = li_index + _keys[i].length();
if (li_legnth == _key.length()) {
if (li_index == 0) {//處理單獨一個關鍵字的情況,例如:if else 等
m_doc.setCharacterAttributes(_start, _keys[i].length(),
keyAttr, false);
} else {//處理關鍵字前面還有字元的情況,例如:)if ;else 等
char ch_temp = _key.charAt(li_index - 1);
if (isCharacter(ch_temp)) {
m_doc.setCharacterAttributes(_start + li_index,
_keys[i].length(), keyAttr, false);
}
}
} else {
if (li_index == 0) {//處理關鍵字後面還有字元的情況,例如:if( end;等
char ch_temp = _key.charAt(_keys[i].length());
if (isCharacter(ch_temp)) {
m_doc.setCharacterAttributes(_start, _keys[i].length(),
keyAttr, false);
}
} else {//處理關鍵字前面和後面都有字元的情況,例如:)if( 等
char ch_temp = _key.charAt(li_index - 1);
char ch_temp_2 = _key.charAt(li_legnth);
if (isCharacter(ch_temp) && isCharacter(ch_temp_2)) {
m_doc.setCharacterAttributes(_start + li_index,
_keys[i].length(), keyAttr, false);
}
}
}
}
return _length + 1;
}
/**
* 處理一行的資料
* @param _start
* @param _end
*/
private void dealText(int _start, int _end) {
String text = "";
try {
text = m_doc.getText(_start, _end - _start).toUpperCase();
} catch (BadLocationException e) {
e.printStackTrace();
}
if (text == null || text.equals("")) {
return;
}
int xStart = 0;
// 析關鍵字---
m_doc.setCharacterAttributes(_start, text.length(), normalAttr, false);
MyStringTokenizer st = new MyStringTokenizer(text);
while (st.hasMoreTokens()) {
String s = st.nextToken();
if (s == null)
return;
xStart = st.getCurrPosition();
setKeyColor(s.toLowerCase(), _start + xStart, s.length());
}
setBracketColor(text);
inputAttributes.addAttributes(normalAttr);
}
/**
* 在進行文字修改的時候
* 獲得游標所在行,只對該行進行處理
*/
private void dealSingleRow() {
Element root = m_doc.getDefaultRootElement();
// 游標當前行
int cursorPos = this.getCaretPosition(); // 前游標的位置
int line = root.getElementIndex(cursorPos);// 當前行
Element para = root.getElement(line);
int start = para.getStartOffset();
int end = para.getEndOffset() - 1;// 除\r字元
dealText(start, end);
}
/**
* 在初始化面板的時候呼叫該方法,
* 查詢整個篇幅的關鍵字
*/
public void syntaxParse() {
Element root = m_doc.getDefaultRootElement();
int li_count = root.getElementCount();
for (int i = 0; i < li_count; i++) {
Element para = root.getElement(i);
int start = para.getStartOffset();
int end = para.getEndOffset() - 1;// 除\r字元
dealText(start, end);
}
}
}
/**
* 在分析字串的同時,記錄每個token所在的位置
*
*/
class MyStringTokenizer extends StringTokenizer {
String sval = " ";
String oldStr, str;
int m_currPosition = 0, m_beginPosition = 0;
MyStringTokenizer(String str) {
super(str, " ");
this.oldStr = str;
this.str = str;
}
public String nextToken() {
try {
String s = super.nextToken();
int pos = -1;
if (oldStr.equals(s)) {
return s;
}
pos = str.indexOf(s + sval);
if (pos == -1) {
pos = str.indexOf(sval + s);
if (pos == -1)
return null;
else
pos += 1;
}
int xBegin = pos + s.length();
str = str.substring(xBegin);
m_currPosition = m_beginPosition + pos;
m_beginPosition = m_beginPosition + xBegin;
return s;
} catch (java.util.NoSuchElementException ex) {
ex.printStackTrace();
return null;
}
}
// 返回token在字串中的位置
public int getCurrPosition() {
return m_currPosition;
}
}