?? mytextpane.java
字號:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import java.util.*;
import java.io.*;
/**
* Description:
* <br/>Copyright (C), 2005-2008, Yeeku.H.Lee
* <br/>This program is protected by copyright laws.
* <br/>Program Name:
* <br/>Date:
* @author Yeeku.H.Lee kongyeeku@163.com
* @version 1.0
*/
public class MyTextPane extends JTextPane
{
protected StyledDocument doc;
protected SyntaxFormatter formatter = new SyntaxFormatter("my.stx");
//定義該文檔的普通文本的外觀屬性
private SimpleAttributeSet normalAttr = formatter.getNormalAttributeSet();
private SimpleAttributeSet quotAttr = new SimpleAttributeSet();
//保存文檔改變的開始位置
private int docChangeStart = 0;
//保存文檔改變的長度
private int docChangeLength = 0;
public MyTextPane()
{
StyleConstants.setForeground(quotAttr, new Color(255, 0 , 255));
StyleConstants.setFontSize(quotAttr, 16);
this.doc = super.getStyledDocument();
//設置該文檔的頁邊距
this.setMargin(new Insets(3, 40, 0, 0));
//添加按鍵監聽器,當按鍵松開時進行語法分析
this.addKeyListener(new KeyAdapter()
{
public void keyReleased(KeyEvent ke)
{
syntaxParse();
}
});
//添加文檔監聽器
doc.addDocumentListener(new DocumentListener()
{
//當Document的屬性或屬性集發生了改變時觸發該方法
public void changedUpdate(DocumentEvent e)
{
}
//當向Document中插入文本時觸發該方法
public void insertUpdate(DocumentEvent e)
{
docChangeStart = e.getOffset();
docChangeLength = e.getLength();
}
//當從Document中刪除文本時觸發該方法
public void removeUpdate(DocumentEvent e)
{
}
});
}
public void syntaxParse()
{
try
{
//獲取文檔的根元素,即文檔內的全部內容
Element root = doc.getDefaultRootElement();
//獲取文檔中光標插入符的位置
int cursorPos = this.getCaretPosition();
int line = root.getElementIndex(cursorPos);
//獲取光標所在位置的行
Element para = root.getElement(line);
//定義光標所在行的行頭在文檔中位置
int start = para.getStartOffset();
//如果文檔修改位置比當前行還前
if (start > docChangeStart)
{
start = docChangeStart;
}
//定義被修改部分的長度
int length = para.getEndOffset() - start;
if (length < docChangeLength)
{
length = docChangeLength + 1;
}
//取出所有被修改的字符串
String s = doc.getText(start, length);
//以空格、點號等作為分隔符
String[] tokens = s.split("\\s+|\\.|\\(|\\)|\\{|\\}|\\[|\\]");
//定義當前分析單詞的在s字符串中的開始位置
int curStart = 0;
boolean isQuot = false;
for (String token : tokens)
{
//找出當前分析單詞在s字符串的中位置
int tokenPos = s.indexOf(token , curStart);
if (isQuot && (token.endsWith("\"") || token.endsWith("\'")))
{
doc.setCharacterAttributes(start + tokenPos, token.length(), quotAttr, false);
isQuot = false;
}
else if (isQuot && !(token.endsWith("\"") || token.endsWith("\'")))
{
doc.setCharacterAttributes(start + tokenPos, token.length(), quotAttr, false);
}
else if ((token.startsWith("\"") || token.startsWith("\'"))
&& (token.endsWith("\"") || token.endsWith("\'")))
{
doc.setCharacterAttributes(start + tokenPos, token.length(), quotAttr, false);
}
else if ((token.startsWith("\"") || token.startsWith("\'"))
&& !(token.endsWith("\"") || token.endsWith("\'")))
{
doc.setCharacterAttributes(start + tokenPos, token.length(), quotAttr, false);
isQuot = true;
}
else
{
//使用格式器對當前單詞設置顏色
formatter.setHighLight(doc , token , start + tokenPos, token.length());
}
//開始分析下一個單詞
curStart = tokenPos + token.length();
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
//重畫該組件,設置行號
public void paint(Graphics g)
{
super.paint(g);
Element root = doc.getDefaultRootElement();
//獲得行號
int line = root.getElementIndex(doc.getLength());
//設置顏色
g.setColor(new Color(230, 230, 230));
//繪制行數矩形框
g.fillRect(0, 0, this.getMargin().left - 10, getSize().height);
//設置行號的顏色
g.setColor(new Color(40, 40, 40));
//每行繪制一個行號
for (int count = 0, j = 1; count <= line; count++, j++)
{
g.drawString(String.valueOf(j), 3,
(int)((count + 1) * 1.535 * StyleConstants.getFontSize(normalAttr)));
}
}
public static void main(String[] args)
{
JFrame frame = new JFrame("文本編輯器");
//使用MyTextPane
frame.getContentPane().add(new JScrollPane(new MyTextPane()));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final int inset = 50;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
frame.setBounds ( inset, inset, screenSize.width - inset*2, screenSize.height - inset*2 );
frame.setVisible(true);
}
}
//定義語法格式器
class SyntaxFormatter
{
//以一個Map保存關鍵字和顏色的對應關系
private Map<SimpleAttributeSet , ArrayList> attMap
= new HashMap<SimpleAttributeSet , ArrayList>();
//定義文檔的正常文本的外觀屬性
SimpleAttributeSet normalAttr = new SimpleAttributeSet();
public SyntaxFormatter(String syntaxFile)
{
//設置正常文本的顏色、大小
StyleConstants.setForeground(normalAttr, Color.BLACK);
StyleConstants.setFontSize(normalAttr, 16);
//創建一個Scanner對象,負責根據語法文件加載顏色信息
Scanner scaner = null;
try
{
scaner = new Scanner(new File(syntaxFile));
}
catch (FileNotFoundException e)
{
throw new RuntimeException("丟失語法文件:" + e.getMessage());
}
int color = -1;
ArrayList<String> keywords = new ArrayList<String>();
//不斷讀取語法文件的內容行
while(scaner.hasNextLine())
{
String line = scaner.nextLine();
//如果當前行以#開頭
if (line.startsWith("#"))
{
if (keywords.size() > 0 && color > -1)
{
//取出當前行的顏色值,并封裝成SimpleAttributeSet對象
SimpleAttributeSet att = new SimpleAttributeSet();
StyleConstants.setForeground(att, new Color(color));
StyleConstants.setFontSize(att, 16);
//將當前顏色和關鍵字List對應起來
attMap.put(att , keywords);
}
//重新創建新的關鍵字List,為下一個語法格式準備
keywords = new ArrayList<String>();
color = Integer.parseInt(line.substring(1) , 16);
}
else
{
//對于普通行,每行內容添加到關鍵字List里
if (line.trim().length() > 0)
{
keywords.add(line.trim());
}
}
}
//把最后的關鍵字和顏色對應起來
if (keywords.size() > 0 && color > -1)
{
SimpleAttributeSet att = new SimpleAttributeSet();
StyleConstants.setForeground(att, new Color(color));
StyleConstants.setFontSize(att, 16);
attMap.put(att , keywords);
}
}
//返回該格式器里正常文本的外觀屬性
public SimpleAttributeSet getNormalAttributeSet()
{
return normalAttr;
}
//設置語法高亮
public void setHighLight(StyledDocument doc , String token ,
int start , int length)
{
//保存需要對當前單詞對應的外觀屬性
SimpleAttributeSet currentAttributeSet = null;
outer :
for (SimpleAttributeSet att : attMap.keySet())
{
//取出當前顏色對應的所有關鍵字
ArrayList keywords = attMap.get(att);
//遍歷所有關鍵字
for (Object keyword : keywords)
{
//如果該關鍵字與當前單詞相同
if (keyword.toString().equals(token))
{
//跳出循環,并設置當前單詞對應的外觀屬性
currentAttributeSet = att;
break outer;
}
}
}
//如果當前單詞對應的外觀屬性不為空
if (currentAttributeSet != null)
{
//設置當前單詞的顏色
doc.setCharacterAttributes(start, length, currentAttributeSet, false);
}
//否則使用普通外觀來設置該單詞
else
{
doc.setCharacterAttributes(start, length, normalAttr, false);
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -