`
lushuaiyin
  • 浏览: 705299 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

关键字着色

 
阅读更多

写自己的文本编辑器(): 高亮关键字

. 高亮的内容:

需要高亮的内容有:

1. 关键字, public, int, true .

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

3. 数字

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

5. 高亮单行注释

6. 高亮多行注释


. 实现高亮的核心方法:

StyledDocument.setCharacterAttributes(intoffset, intlength, AttributeSets, booleanreplace)


. 文本编辑器选择.

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) {}

}

}

}

分享到:
评论

相关推荐

    richEdit关键字着色

    在编程中,特别是在开发文本编辑器或者代码编辑器时,我们常常需要实现“关键字着色”功能,也就是根据预定义的关键字将文本中的特定词汇高亮显示,以便于用户更好地理解和阅读代码。这在编程语言学习、代码编写和...

    关键字 着色 C# .NET 识别

    本篇文章将深入探讨如何在C# .NET环境下实现关键字着色功能。 首先,我们需要了解C#语言的关键字。C#是一门面向对象的编程语言,它包含一系列内置关键字,如`class`、`public`、`private`、`void`、`if`、`else`等...

    简单的JavaScript关键字着色程序

    自己写的一个简单的js关键字着色程序。只有100来 行,很简单只要熟悉正则都能看懂。放在这一来为了 备份,二来为了和大家交流。后期会写一个js格式化 的程序,将来会将这段代码整合的里面

    vb语法着色控件,可以方便的实现关键字着色,以及显示行标号,附带范例

    1. **关键字着色**:关键字是编程语言中具有特殊含义的标识符,如“Dim”、“For”、“If”等。控件能够自动识别这些关键字并赋予特定颜色,帮助程序员快速区分和理解代码结构。 2. **行号显示**:在代码编辑器中...

    珍贵的 关键字着色 代码缩进 完美版,还有很多高级类封装

    珍贵的 关键字着色 代码缩进 完美版,还有很多高级类封装,是我存了3年的好东西。一直用到今天。1年前还有一个类也是很珍贵的。 我一般不乱发资源。要发就是最好的东西来分享,所有的类都是独立的。拖进你的项目绝...

    JTextPane 关键字变色

    在给定的标题“JTextPane 关键字变色”和描述“SWT JTextPane 可以把控件中需要的字符串的颜色修改成自己想要的颜色”中,我们关注的主要知识点是`JTextPane`如何实现特定关键字的高亮显示,也就是改变颜色。...

    MasmEditor汇编集成编辑调试环境V1.6

    除了具有关键字着色的编辑环境外,可以通过外部集成的方式在界面中编译、连接、调试可执行文件,更重要的是对于8086/8088指令系统可以进行源码调试,可以实时的对寄存器、标志位、内存数据进行监视修改,还具备设置...

    MasmEditor1.6.0.5汇编语言

    除了具有关键字着色的编辑环境外,可以通过外部集成的方式在界面中编译、连接、调试可执行文件,更重要的是对于8086/8088指令系统可以进行源码调试,可以实时的对寄存器、标志位、内存数据进行监视修改,还具备设置...

    JavaSE编 辑 器

    Java Studio 是一个组件可扩充的 Java 开发环境,它是我和我哥哥模仿visual studio界面用Notepad全手工打造的Java期末考核项目,就冒昧叫她Java Studio吧,大家见笑。... Java关键字着色 Java Runtime Process

    MDK配色方案及操作方法

    自定义关键字着色显示高亮的效果 自定义关键字在arm.pro文件中已增加了一些常用关键词的高亮,如果没有你想要的关键词可以按以下格式添加,很简单的。 配色方案的配置方法 首先安装 Cascadia Code 字体文件(可...

    Emedit编辑工具,一个比记事本功能更强的编辑工具

    其次,Emedit具有编程语言关键字着色功能。这意味着不同类型的代码元素(如变量、函数、关键字)会以不同的颜色显示,这极大地提高了代码的可读性。色彩编码使得在大量代码中快速定位特定元素成为可能,减少了出错的...

    编译原理课程设计 MFC实现

    采用MFC多文档和递归子程序法实现,支持关键字着色,IDE集成开发环境,使用方便,得到了大家的一致好评,本人更是得到了最高分99分。实现了基本C语言的顺序、分支和循环语句,变量要提前声明。支持int型和char型,...

    jcolorize:用于为日志文件着色的命令行工具,尤其是Apache Tomcat和Wildfly AS的日志文件

    jcolorize 从FILE或stdin读取,为某些关键字着色并写入stdout。 专门设计用于着色Apache Tomcat和Wildfly AS的日志文件。 Usage: jcolorize [FILE]Examples:jcolorize server.log | less [-R]cat server.log | ...

    RustAdminRelease (1).zip

    关键字着色是RustAdmin的一个特色功能,它能帮助管理员快速识别和理解配置文件中的关键内容。在配置文件中,特定的关键字会被高亮显示,使得查找和修改配置变得直观且高效,尤其对于初学者来说,这是一个非常友好的...

    editplus的ice语法文件

    editplus的ice语法文件,支持关键字着色等。基于c++的语法文件自己整理的。

    editplus中文版

    "提供多种语言的关键字着色"是指EditPlus支持对不同编程语言的关键字进行颜色区分,使得代码更加易于阅读和理解。这种颜色编码通常包括变量、关键字、函数、注释等不同元素,每种元素都有特定的颜色标识,如蓝色代表...

    EmEditor用于打开大型文本文件

    用于打开大文本文件、大型记事本文件、分页打开、关键字着色和Vs相似,而且支持类似region折叠,非常好用!

    editplus 编辑器

    很好用的,,适合计算机爱好者,关键字着色,最适合编辑程序语言,java,c/c++.html,等等

Global site tag (gtag.js) - Google Analytics