青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

逛奔的蝸牛

我不聰明,但我會很努力

   ::  :: 新隨筆 ::  ::  :: 管理 ::

寫自己的文本編輯器(): 高亮關鍵字

. 高亮的內容:

需要高亮的內容有:

1. 關鍵字, public, int, true

2. 運算符, +, -, *, /

3. 數字

4. 高亮字符串, "example of string"

5. 高亮單行注釋

6. 高亮多行注釋


. 實現高亮的核心方法:

StyledDocument.setCharacterAttributes(int offset, int length, AttributeSet s, boolean replace) 


. 文本編輯器選擇.

Java中提供的多行文本編輯器有: JTextComponent, JTextArea, JTextPane, JEditorPane, 都可以使用. 但是因為語法著色中文本要使用多種風格的樣式, 所以這些文本編輯器的document要使用StyledDocument. 

JTextArea使用的是PlainDocument, document不能進行多種格式的著色.

JTextPane, JEditorPane使用的是StyledDocument, 默認就可以使用

為了實現語法著色, 可以繼承自DefaultStyledDocument, 設置其為這些文本編輯器的documet, 或者也可以直接使用JTextPane, JEditorPane來做. 為了方便, 這里就直接使用JTextPane.


. 何時進行著色.

當文本編輯器中有字符被插入或者刪除時, 文本的內容就發生了變化, 這時檢查, 進行著色.

為了監視到文本的內容發生了變化, 要給document添加一個DocumentListener監聽器, 在他的removeUpdateinsertUpdate中進行著色處理.

changedUpdate方法在文本的屬性例如前景色, 背景色, 字體等風格改變時才會被調用.

@Override

public void changedUpdate(DocumentEvent e) {


}


@Override

public void insertUpdate(DocumentEvent e) {

try {

colouring((StyledDocument) e.getDocument(), e.getOffset(), e.getLength());

} catch (BadLocationException e1) {

e1.printStackTrace();

}

}


@Override

public void removeUpdate(DocumentEvent e) {

try {

// 因為刪除后光標緊接著影響的單詞兩邊, 所以長度就不需要了

colouring((StyledDocument) e.getDocument(), e.getOffset(), 0);

} catch (BadLocationException e1) {

e1.printStackTrace();

}

}


. 著色范圍

pos: 指變化前光標的位置.

len: 指變化的字符數.

例如有關鍵字public, int

單詞"publicint", "public""int"中插入一個空格后變成"public int", 一個單詞變成了兩個, 這時對"public" "int"進行著色.

著色范圍是publicp的位置和intt的位置加1, 即是pos前面單詞開始的下標和pos+len開始單詞結束的下標. 所以上例中要著色的范圍是"public int". 

提供了方法indexOfWordStart來取得pos前單詞開始的下標, 方法indexOfWordEnd來取得pos后單詞結束的下標.

public int indexOfWordStart(Document doc, int pos) throws BadLocationException {

// pos開始向前找到第一個非單詞字符.

for (; pos > 0 && isWordCharacter(doc, pos - 1); --pos);

return pos;

}


public int indexOfWordEnd(Document doc, int pos) throws BadLocationException {

// pos開始向前找到第一個非單詞字符.

for (; isWordCharacter(doc, pos); ++pos);

return pos;

}



一個字符是單詞的有效字符: 是字母, 數字, 下劃線.

public boolean isWordCharacter(Document doc, int pos) throws BadLocationException {

char ch = getCharAt(doc, pos); // 取得在文檔中pos位置處的字符

if (Character.isLetter(ch) || Character.isDigit(ch) || ch == '_') { return true; }

return false;

}


所以著色的范圍是[start, end] :

int start = indexOfWordStart(doc, pos);

int end = indexOfWordEnd(doc, pos + len);


. 關鍵字著色.

從著色范圍的開始下標起進行判斷, 如果是以字母開或者下劃線開頭, 則說明是單詞, 那么先取得這個單詞, 如果這個單詞是關鍵字, 就進行關鍵字著色, 如果不是, 就進行普通的著色. 著色完這個單詞后, 繼續后面的著色處理. 已經著色過的字符, 就不再進行著色了.

public void colouring(StyledDocument doc, int pos, int len) throws BadLocationException {

// 取得插入或者刪除后影響到的單詞.

// 例如"public"b后插入一個空格, 就變成了:"pub lic", 這時就有兩個單詞要處理:"pub""lic"

// 這時要取得的范圍是pubp前面的位置和licc后面的位置

int start = indexOfWordStart(doc, pos);

int end = indexOfWordEnd(doc, pos + len);


char ch;

while (start < end) {

ch = getCharAt(doc, start);

if (Character.isLetter(ch) || ch == '_') {

// 如果是以字母或者下劃線開頭, 說明是單詞

// pos為處理后的最后一個下標

start = colouringWord(doc, start);

} else {

//SwingUtilities.invokeLater(new ColouringTask(doc, pos, wordEnd - pos, normalStyle));

++start;

}

}

}



public int colouringWord(StyledDocument doc, int pos) throws BadLocationException {

int wordEnd = indexOfWordEnd(doc, pos);

String word = doc.getText(pos, wordEnd - pos); // 要進行著色的單詞


if (keywords.contains(word)) {

// 如果是關鍵字, 就進行關鍵字的著色, 否則使用普通的著色.

// 這里有一點要注意, insertUpdateremoveUpdate的方法調用的過程中, 不能修改doc的屬性.

// 但我們又要達到能夠修改doc的屬性, 所以把此任務放到這個方法的外面去執行.

// 實現這一目的, 可以使用新線程, 但放到swing的事件隊列里去處理更輕便一點.

SwingUtilities.invokeLater(new ColouringTask(doc, pos, wordEnd - pos, keywordStyle));

} else {

SwingUtilities.invokeLater(new ColouringTask(doc, pos, wordEnd - pos, normalStyle));

}


return wordEnd;

}


因為在insertUpdateremoveUpdate方法中不能修改document的屬性, 所以著色的任務放到這兩個方法外面, 所以使用了SwingUtilities.invokeLater來實現.

private class ColouringTask implements Runnable {

private StyledDocument doc;

private Style style;

private int pos;

private int len;


public ColouringTask(StyledDocument doc, int pos, int len, Style style) {

this.doc = doc;

this.pos = pos;

this.len = len;

this.style = style;

}


public void run() {

try {

// 這里就是對字符進行著色

doc.setCharacterAttributes(pos, len, style, true);

} catch (Exception e) {}

}

}



: 源碼

關鍵字著色的完成代碼如下, 可以直接編譯運行. 對于數字, 運算符, 字符串等的著色處理在以后的教程中會繼續進行詳解.

import java.awt.Color;

import java.util.HashSet;

import java.util.Set;


import javax.swing.JFrame;

import javax.swing.JTextPane;

import javax.swing.SwingUtilities;

import javax.swing.event.DocumentEvent;

import javax.swing.event.DocumentListener;

import javax.swing.text.BadLocationException;

import javax.swing.text.Document;

import javax.swing.text.Style;

import javax.swing.text.StyleConstants;

import javax.swing.text.StyledDocument;


public class HighlightKeywordsDemo {

public static void main(String[] args) {

JFrame frame = new JFrame();


JTextPane editor = new JTextPane();

editor.getDocument().addDocumentListener(new SyntaxHighlighter(editor));

frame.getContentPane().add(editor);


frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setSize(500, 500);

frame.setVisible(true);

}

}


/**

 * 當文本輸入區的有字符插入或者刪除時, 進行高亮.

 * 

 * 要進行語法高亮, 文本輸入組件的document要是styled document才行. 所以不要用JTextArea. 可以使用JTextPane.

 * 

 * @author Biao

 * 

 */

class SyntaxHighlighter implements DocumentListener {

private Set<String> keywords;

private Style keywordStyle;

private Style normalStyle;


public SyntaxHighlighter(JTextPane editor) {

// 準備著色使用的樣式

keywordStyle = ((StyledDocument) editor.getDocument()).addStyle("Keyword_Style", null);

normalStyle = ((StyledDocument) editor.getDocument()).addStyle("Keyword_Style", null);

StyleConstants.setForeground(keywordStyle, Color.RED);

StyleConstants.setForeground(normalStyle, Color.BLACK);


// 準備關鍵字

keywords = new HashSet<String>();

keywords.add("public");

keywords.add("protected");

keywords.add("private");

keywords.add("_int9");

keywords.add("float");

keywords.add("double");

}


public void colouring(StyledDocument doc, int pos, int len) throws BadLocationException {

// 取得插入或者刪除后影響到的單詞.

// 例如"public"b后插入一個空格, 就變成了:"pub lic", 這時就有兩個單詞要處理:"pub""lic"

// 這時要取得的范圍是pubp前面的位置和licc后面的位置

int start = indexOfWordStart(doc, pos);

int end = indexOfWordEnd(doc, pos + len);


char ch;

while (start < end) {

ch = getCharAt(doc, start);

if (Character.isLetter(ch) || ch == '_') {

// 如果是以字母或者下劃線開頭, 說明是單詞

// pos為處理后的最后一個下標

start = colouringWord(doc, start);

} else {

SwingUtilities.invokeLater(new ColouringTask(doc, start, 1, normalStyle));

++start;

}

}

}


/**

* 對單詞進行著色, 并返回單詞結束的下標.

* @param doc

* @param pos

* @return

* @throws BadLocationException

*/

public int colouringWord(StyledDocument doc, int pos) throws BadLocationException {

int wordEnd = indexOfWordEnd(doc, pos);

String word = doc.getText(pos, wordEnd - pos);


if (keywords.contains(word)) {

// 如果是關鍵字, 就進行關鍵字的著色, 否則使用普通的著色.

// 這里有一點要注意, insertUpdateremoveUpdate的方法調用的過程中, 不能修改doc的屬性.

// 但我們又要達到能夠修改doc的屬性, 所以把此任務放到這個方法的外面去執行.

// 實現這一目的, 可以使用新線程, 但放到swing的事件隊列里去處理更輕便一點.

SwingUtilities.invokeLater(new ColouringTask(doc, pos, wordEnd - pos, keywordStyle));

} else {

SwingUtilities.invokeLater(new ColouringTask(doc, pos, wordEnd - pos, normalStyle));

}


return wordEnd;

}


/**

* 取得在文檔中下標在pos處的字符.

* 如果posdoc.getLength(), 返回的是一個文檔的結束符, 不會拋出異常. 如果pos<0, 則會拋出異常.

* 所以pos的有效值是[0, doc.getLength()]

* @param doc

* @param pos

* @return

* @throws BadLocationException

*/

public char getCharAt(Document doc, int pos) throws BadLocationException {

return doc.getText(pos, 1).charAt(0);

}


/**

* 取得下標為pos, 它所在的單詞開始的下標. ±wor^d± (^表示pos, ±表示開始或結束的下標)

* @param doc

* @param pos

* @return

* @throws BadLocationException

*/

public int indexOfWordStart(Document doc, int pos) throws BadLocationException {

// pos開始向前找到第一個非單詞字符.

for (; pos > 0 && isWordCharacter(doc, pos - 1); --pos);


return pos;

}


/**

* 取得下標為pos, 它所在的單詞結束的下標. ±wor^d± (^表示pos, ±表示開始或結束的下標)

* @param doc

* @param pos

* @return

* @throws BadLocationException

*/

public int indexOfWordEnd(Document doc, int pos) throws BadLocationException {

// pos開始向前找到第一個非單詞字符.

for (; isWordCharacter(doc, pos); ++pos);


return pos;

}


/**

* 如果一個字符是字母, 數字, 下劃線, 則返回true.

* @param doc

* @param pos

* @return

* @throws BadLocationException

*/

public boolean isWordCharacter(Document doc, int pos) throws BadLocationException {

char ch = getCharAt(doc, pos);

if (Character.isLetter(ch) || Character.isDigit(ch) || ch == '_') { return true; }

return false;

}


@Override

public void changedUpdate(DocumentEvent e) {


}


@Override

public void insertUpdate(DocumentEvent e) {

try {

colouring((StyledDocument) e.getDocument(), e.getOffset(), e.getLength());

} catch (BadLocationException e1) {

e1.printStackTrace();

}

}


@Override

public void removeUpdate(DocumentEvent e) {

try {

// 因為刪除后光標緊接著影響的單詞兩邊, 所以長度就不需要了

colouring((StyledDocument) e.getDocument(), e.getOffset(), 0);

} catch (BadLocationException e1) {

e1.printStackTrace();

}

}


/**

* 完成著色任務

* @author Biao

*/

private class ColouringTask implements Runnable {

private StyledDocument doc;

private Style style;

private int pos;

private int len;


public ColouringTask(StyledDocument doc, int pos, int len, Style style) {

this.doc = doc;

this.pos = pos;

this.len = len;

this.style = style;

}


public void run() {

try {

// 這里就是對字符進行著色

doc.setCharacterAttributes(pos, len, style, true);

} catch (Exception e) {}

}

}

}

posted on 2010-02-05 19:00 逛奔的蝸牛 閱讀(9216) 評論(0)  編輯 收藏 引用 所屬分類: Java
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲视频欧洲视频| 香港久久久电影| 欧美日韩另类一区| 嫩草影视亚洲| 欧美国产日韩在线观看| 免费在线成人av| 欧美精品自拍偷拍动漫精品| 欧美成人四级电影| 欧美日韩 国产精品| 国产精品精品视频| 国产亚洲欧美激情| 亚洲日本aⅴ片在线观看香蕉| 亚洲精品国产无天堂网2021| 一区二区三区免费网站| 欧美一区二区久久久| 久久这里只有| 日韩一区二区精品| 久久精品国产免费观看| 欧美大片免费| 国产欧美1区2区3区| 亚洲国产精品久久91精品| 在线综合亚洲| 久久偷看各类wc女厕嘘嘘偷窃| 欧美激情免费观看| 亚洲欧美在线一区二区| 麻豆成人在线播放| 国产精品爽爽爽| 亚洲精品日韩在线观看| 欧美在线观看视频在线 | 在线精品一区二区| 一本综合精品| 免费不卡在线观看| 亚洲一区二区三区乱码aⅴ| 免费成人美女女| 国产日韩欧美制服另类| 日韩视频一区二区在线观看 | 亚洲欧美一区二区在线观看| 免费观看日韩| 久久精品亚洲一区二区| 国产精品久久二区| 99热免费精品| 欧美xxxx在线观看| 欧美一区二区日韩一区二区| 欧美日韩国产精品自在自线| 一区二区三区四区五区精品| 久久综合色8888| 亚洲调教视频在线观看| 欧美成人高清| 亚洲国产二区| 裸体一区二区| 欧美亚洲三区| 国产免费亚洲高清| 午夜精品av| 亚洲视频电影图片偷拍一区| 欧美激情在线| 一本色道久久综合亚洲精品按摩| 欧美电影在线播放| 久久夜色精品国产亚洲aⅴ| 国产视频亚洲精品| 欧美中在线观看| 亚洲免费影视第一页| 国产精品卡一卡二卡三| 亚洲欧美高清| 亚洲欧美日韩国产精品| 国产精品一区二区三区观看| 亚洲欧美日韩在线观看a三区| 一本高清dvd不卡在线观看| 欧美性猛交一区二区三区精品| 中文亚洲欧美| 亚洲男人第一av网站| 国产婷婷色一区二区三区在线 | 亚洲二区视频在线| 亚洲第一天堂av| 欧美成人高清| 亚洲天堂av高清| 亚洲欧美影音先锋| 伊人男人综合视频网| 欧美暴力喷水在线| 欧美久久99| 亚洲欧美中文字幕| 久久精品91| 亚洲精选久久| 午夜在线a亚洲v天堂网2018| 黄色综合网站| 亚洲精品国产精品乱码不99 | 亚洲国产欧美一区二区三区久久 | 久久免费高清| 免费欧美日韩国产三级电影| 亚洲精品你懂的| 亚洲桃色在线一区| 伊人成人开心激情综合网| 亚洲二区精品| 国产精品自拍视频| 欧美激情一级片一区二区| 欧美网站在线观看| 蜜臀久久99精品久久久画质超高清| 欧美国产日韩免费| 久久精品日韩一区二区三区| 噜噜噜在线观看免费视频日韩| 亚洲日韩视频| 国产免费观看久久黄| 欧美激情中文字幕乱码免费| 国产精品久久久久aaaa九色| 美女福利精品视频| 国产精品a久久久久| 蜜桃伊人久久| 国产精品亚洲网站| 最新亚洲一区| 伊人久久大香线蕉综合热线| 99精品免费视频| 91久久黄色| 久久久久久日产精品| 欧美一区二区在线播放| 欧美日韩国产精品| 欧美激情黄色片| 狠狠色狠狠色综合| 亚洲欧美日韩国产综合在线 | 久久网站热最新地址| 欧美视频在线一区| 欧美大片在线看| 国产主播一区二区| 亚洲自拍啪啪| 午夜精品一区二区三区电影天堂 | 亚洲欧美日韩国产一区二区| 一区二区三区成人| 欧美国产欧美综合| 亚洲二区免费| 91久久久精品| 欧美成人资源网| 亚洲电影激情视频网站| 亚洲二区在线视频| 久久精品亚洲热| 鲁大师影院一区二区三区| 国产欧美一区二区精品性色| 亚洲一区区二区| 午夜精品区一区二区三| 国产精品久久久久免费a∨大胸 | 久久夜色精品国产亚洲aⅴ| 国产嫩草影院久久久久| 亚洲午夜精品一区二区| 亚洲欧美成人一区二区在线电影| 欧美日韩国产a| 夜夜狂射影院欧美极品| 亚洲一区自拍| 国产精品一区二区三区四区五区 | 亚洲视频成人| 国产精品国产三级国产普通话99 | 亚洲久久一区二区| 欧美一区二区大片| 国产永久精品大片wwwapp| 久久精品日韩欧美| 欧美国产视频一区二区| 日韩亚洲欧美在线观看| 欧美日韩一区二区三区四区五区 | 亚洲精品综合| 欧美午夜无遮挡| 性欧美8khd高清极品| 美女在线一区二区| 日韩一区二区电影网| 国产精品第十页| 久久9热精品视频| 欧美激情网友自拍| 一本色道久久综合精品竹菊| 国产精品入口夜色视频大尺度| 性伦欧美刺激片在线观看| 欧美**人妖| 亚洲欧美视频| 亚洲国产导航| 国产精品少妇自拍| 狼人天天伊人久久| 夜夜嗨av一区二区三区四区| 欧美在线视频免费| 亚洲日本va午夜在线电影| 国产精品夜夜嗨| 欧美精品免费观看二区| 午夜精品一区二区三区在线| 欧美黄免费看| 久久精品人人做人人爽| 一区二区黄色| 在线成人激情黄色| 国产精品国产福利国产秒拍| 久久综合中文字幕| 午夜天堂精品久久久久| 日韩亚洲视频在线| 欧美高清成人| 久久久久欧美| 欧美亚洲尤物久久| 一区二区精品| 亚洲精品欧美一区二区三区| 国产有码在线一区二区视频| 国产精品大片wwwwww| 免费亚洲一区二区| 久久久精品999| 亚洲午夜视频在线观看| 亚洲国产精品成人综合| 久久天天躁狠狠躁夜夜爽蜜月 | 亚洲免费网站| 日韩一级裸体免费视频| 亚洲高清自拍| 激情综合视频|