DefaultStyledDocument document = new DefaultStyledDocument();
JTextPane textpane = new JTextPane(document);
StyleContext context = new StyleContext();
// build a style
Style style = context.addStyle("test", null);
// set some style properties
StyleConstants.setForeground(style, Color.BLUE);
// add some data to the document
document.insertString(0, "", style);
private final class CustomDocumentFilter extends DocumentFilter
{
private final StyledDocument styledDocument = yourTextPane.getStyledDocument();
private final StyleContext styleContext = StyleContext.getDefaultStyleContext();
private final AttributeSet greenAttributeSet = styleContext.addAttribute(styleContext.getEmptySet(), StyleConstants.Foreground, Color.GREEN);
private final AttributeSet blackAttributeSet = styleContext.addAttribute(styleContext.getEmptySet(), StyleConstants.Foreground, Color.BLACK);
// Use a regular expression to find the words you are looking for
Pattern pattern = buildPattern();
@Override
public void insertString(FilterBypass fb, int offset, String text, AttributeSet attributeSet) throws BadLocationException {
super.insertString(fb, offset, text, attributeSet);
handleTextChanged();
}
@Override
public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
super.remove(fb, offset, length);
handleTextChanged();
}
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attributeSet) throws BadLocationException {
super.replace(fb, offset, length, text, attributeSet);
handleTextChanged();
}
/**
* Runs your updates later, not during the event notification.
*/
private void handleTextChanged()
{
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
updateTextStyles();
}
});
}
/**
* Build the regular expression that looks for the whole word of each word that you wish to find. The "\\b" is the beginning or end of a word boundary. The "|" is a regex "or" operator.
* @return
*/
private Pattern buildPattern()
{
StringBuilder sb = new StringBuilder();
for (String token : ALL_WORDS_THAT_YOU_WANT_TO_FIND) {
sb.append("\\b"); // Start of word boundary
sb.append(token);
sb.append("\\b|"); // End of word boundary and an or for the next word
}
if (sb.length() > 0) {
sb.deleteCharAt(sb.length() - 1); // Remove the trailing "|"
}
Pattern p = Pattern.compile(sb.toString());
return p;
}
private void updateTextStyles()
{
// Clear existing styles
styledDocument.setCharacterAttributes(0, yourTextPane.getText().length(), blackAttributeSet, true);
// Look for tokens and highlight them
Matcher matcher = pattern.matcher(yourTextPane.getText());
while (matcher.find()) {
// Change the color of recognized tokens
styledDocument.setCharacterAttributes(matcher.start(), matcher.end() - matcher.start(), greenAttributeSet, false);
}
}
}
import java.awt.Color;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.TabSet;
import javax.swing.text.TabStop;
/**
* This class is a prototype for a syntax highlighter for java code.
* It highlights common java keywords, boolean values and it highlights digits in the text.
*
* Limitations of the current prototype:
* -It does not highlight comments
* -It does not highlight method calls
* -It does not highlight objects that are not a part of common java keywords
* -It does not have intellisense autosuggestion
*
* Addendum:
* Even though this syntax highlighter is designed for java code, {@link #initializeSyntaxHighlighter()} can be modified to highlight any other programming language or keywords
*/
public class JSyntaxTextPane extends JTextPane {
// Default Styles
final StyleContext cont = StyleContext.getDefaultStyleContext();
AttributeSet defaultForeground = cont.addAttribute(cont.getEmptySet(), StyleConstants.Foreground, Color.white);
AttributeSet defaultNumbers = cont.addAttribute(cont.getEmptySet(), StyleConstants.Foreground, Color.cyan);
public JSyntaxTextPane () {
// Styler
DefaultStyledDocument doc = new DefaultStyledDocument() {
public void insertString (int offset, String str, AttributeSet a) throws BadLocationException {
super.insertString(offset, getDeveloperShortcuts(str), a);
String text = getText(0, getLength());
int before = findLastNonWordChar(text, offset);
if (before < 0) before = 0;
int after = findFirstNonWordChar(text, offset + str.length());
int wordL = before;
int wordR = before;
while (wordR <= after) {
if (wordR == after || String.valueOf(text.charAt(wordR)).matches("\\W")) {
// Colors words in appropriate style, if nothing matches, make it default black
boolean matchFound = false;
for (KeyWord keyWord : keyWords) {
if (text.substring(wordL, wordR).matches("(\\W)*("+keyWord.getWords()+")")) {
setCharacterAttributes(wordL, wordR - wordL, keyWord.getColorAttribute(), false);
matchFound = true;
}
}
// Highlight numbers
if (text.substring(wordL, wordR).matches("\\W\\d[\\d]*")) {
setCharacterAttributes(wordL, wordR - wordL, defaultNumbers, false);
matchFound = true;
}
// ================ ANY ADDITIONAL HIGHLIGHTING LOGIC MAY BE ADDED HERE
// Ideas: highlighting a comment; highlighting method calls;
// ================
// If no match found, make text default colored
if(!matchFound) {
setCharacterAttributes(wordL, wordR - wordL, defaultForeground, false);
}
wordL = wordR;
}
wordR++;
}
}
public void remove (int offs, int len) throws BadLocationException {
super.remove(offs, len);
String text = getText(0, getLength());
int before = findLastNonWordChar(text, offs);
if (before < 0) before = 0;
int after = findFirstNonWordChar(text, offs);
// Colors words in appropriate style, if nothing matches, make it default black
boolean matchFound = false;
for (KeyWord keyWord : keyWords) {
if (text.substring(before, after).matches("(\\W)*("+keyWord.getWords()+")")) {
setCharacterAttributes(before, after - before, keyWord.getColorAttribute(), false);
matchFound = true;
}
// Highlight numbers
if (text.substring(before, after).matches("\\W\\d[\\d]*")) {
setCharacterAttributes(before, after - before, defaultNumbers, false);
matchFound = true;
}
// ================ ANY ADDITIONAL HIGHLIGHTING LOGIC MAY BE ADDED HERE
// Ideas: highlighting a comment; highlighting method calls;
// ================
if(!matchFound) {
setCharacterAttributes(before, after - before, defaultForeground, false);
}
}
}
};
setStyledDocument(doc);
// SET DEFAULT TAB SIZE
setTabSize(40);
// THIS PART APPLIES DEFAULT SYNTAX HIGHLIGHTER BEHAVIOUR
initializeSyntaxHighlighter();
}
private int findLastNonWordChar (String text, int index) {
while (--index >= 0) {
if (String.valueOf(text.charAt(index)).matches("\\W")) {
break;
}
}
return index;
}
private int findFirstNonWordChar (String text, int index) {
while (index < text.length()) {
if (String.valueOf(text.charAt(index)).matches("\\W")) {
break;
}
index++;
}
return index;
}
/**
* Shortcuts, when letter is typed, it will produce additional strings specified inside of this method
*
* @param str
* @return
*/
private String getDeveloperShortcuts(String str) {
// Add ending parenthesis when it is open
if(str.equals("(")) {
return "()";
}
// Add ending braces when it is open
if(str.equals("{")) {
return "{\n\n};";
}
return str;
}
/**
* Sets size of space produced when user presses Tab button
*
* @param tabSize
*/
public void setTabSize(int tabSize) {
// Once tab count exceed x times, it will make a small space only
int maxTabsPerRow = 10;
TabStop[] tabs = new TabStop[maxTabsPerRow];
for(int i = 0; i < maxTabsPerRow; i++) {
tabs[i] = new TabStop(tabSize*(i+1), TabStop.ALIGN_LEFT, TabStop.LEAD_NONE);
}
TabSet tabset = new TabSet(tabs);
StyleContext sc = StyleContext.getDefaultStyleContext();
AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY,
StyleConstants.TabSet, tabset);
setParagraphAttributes(aset, false);
}
/**
* Adds a key word or keywords that will be colored in the JTextPane
*
* @param color - color of the words
* @param words - words that need to be colored
*/
public void addKeyWord(Color color, String ...words) {
keyWords.add(new KeyWord(color, words));
}
ArrayList<KeyWord> keyWords = new ArrayList<KeyWord>();
/**
* Holds information about list of words that need to be colored in a specific color
*
*/
class KeyWord {
Color color;
String[] words;
/**
* Instantiates a new key word object that holds a list of words that need to be colored.
*
* @param color the color
* @param words the words
*/
public KeyWord(Color color, String...words) {
this.color = color;
this.words = words;
}
public String getWords() {
String text = "";
for (int i = 0; i < words.length; i++) {
if(i != words.length-1) {
text = text + words[i] + "|";
} else {
text = text + words[i];
}
}
return text;
}
public AttributeSet getColorAttribute() {
StyleContext cont = StyleContext.getDefaultStyleContext();
return cont.addAttribute(cont.getEmptySet(), StyleConstants.Foreground, color);
}
}
/**
* Sets color of all integers
*
* @param color
*/
public void setIntegerColours(Color color) {
defaultNumbers = cont.addAttribute(cont.getEmptySet(), StyleConstants.Foreground, color);
}
/**
* Sets color of non-keywords
*
* @param color
*/
public void setDefaultTextColour(Color color) {
defaultForeground = cont.addAttribute(cont.getEmptySet(), StyleConstants.Foreground, color);
}
/**
* Initializes rules by which textpane should be coloring text
*/
public void initializeSyntaxHighlighter() {
// Set background color
setBackground(Color.black);
// Java keywords
addKeyWord(Color.pink,
"abstract",
"continue",
"for",
"new",
"switch",
"assert",
"default",
"goto",
"package",
"synchronized",
"do",
"if",
"private",
"this",
"break",
"double",
"implements",
"protected",
"throw",
"else",
"import",
"public",
"throws",
"case",
"enum",
"instanceof",
"return",
"transient",
"catch",
"extends",
"short",
"try",
"char",
"final",
"interface",
"static",
"void",
"class",
"finally",
"strictfp",
"volatile",
"const",
"native",
"super",
"while"
);
// Developer's preference
addKeyWord(Color.green,
"true"
);
addKeyWord(Color.red,
"false"
);
addKeyWord(Color.red,
"!"
);
// Java Variables
addKeyWord(Color.yellow,
"String",
"byte", "Byte",
"short", "Short",
"int", "Integer",
"long", "Long",
"float", "Float",
"double", "Double",
"char", "Character",
"boolean", "Boolean");
}
/**
* Demo for testing purposes
*/
public static void main(String[] args) {
// Our Component
JSyntaxTextPane textPane = new JSyntaxTextPane();
textPane.setText("public class Test {\r\n"
+ " int age = 18;\r\n"
+ " String name = \"Gerald\";\r\n"
+ " Long life = 100.50;\r\n"
+ " boolean alive = true;\r\n"
+ " boolean happy = false;\r\n"
+ " \r\n"
+ " // Comment Example\r\n"
+ " public static void shout(int loudness) {\r\n"
+ " System.out.println(loudness);\r\n"
+ " };\r\n"
+ "\r\n"
+ "};");
// JFrame
JFrame frame = new JFrame("Test");
frame.getContentPane().add(textPane);
frame.pack();
frame.setSize(350, 350);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
6条答案
按热度按时间bxpogfeg1#
不可以。你不应该重写paintComponent()方法。相反,你应该使用
StyledDocument
。你还应该自己分隔单词。下面是演示,它会在键入时将“public”、“protected”和“private”变成红色,就像一个简单的代码编辑器:
代码不是很漂亮,因为我打得很快,但它很好用。我希望它能给予你一些提示。
yrwegjxp2#
覆盖
paintComponent
对您没有帮助。这并不容易,但也不是不可能,下面的一些东西会对你有所帮助:
您可能需要对此进行调整,但至少它向您展示了从哪里开始。
vsikbqxv3#
另一种解决方案是使用
DocumentFilter
。下面是一个例子:
创建扩展DocumentFilter的类:
然后,您需要做的就是将创建的
DocumentFilter
应用到JTextPane
,如下所示:ruarlubt4#
您可以像我在这里所做的那样扩展DefaultStyledDocument,以构建一个使用关键字文本着色的SQL编辑器...
只需将其添加到类中,如下所示:
下面是缺少的HiliteWord类...
c3frrgcw5#
@康斯坦丁
亲爱的康斯坦丁,我用你的罚款解决方案为我的小项目,经过几次调整后,你的解决方案为我工作得很好。
如果您允许,我的变更为:
我在自己的JFrame中使用类关键字StyledDocument:
我已更改此行:可变属性集cwStyle =Functions.style(真、假、颜色、红色);
我将cwStyle示例的提供外包给了一个名为style的静态函数:
此外,正如你在上面看到的,cwStyle类不再是StyleConstants的一个示例,而是MutableAttributeSet的一个示例。因此,很自然地,我也必须更改KeywordStyledDocumentClass的构造函数:
经过这一小的变化和添加我自己的“单词”在您的isReservedWord函数和添加我的字符'和 * 到您的processWord函数:
我变成了我渴望的结果:
非常感谢您在这里展示您的代码。
6za6bjd06#
通过使用用户shuangwhywhy代码中的思想,我修改了他的代码并进行了一些改进,我相信这些改进将使许多希望能够在JTextPane中动态突出显示关键字的人受益。
在我的代码中,我扩展了JTextPane并创建了一个名为JSyntaxTextPane的组件。
它允许开发人员声明需要着色/突出显示的单词列表,然后一旦在此组件的文本中找到这些单词,它们将相应地着色。
主要方法:
initializeSyntaxHighlighter()-这是我创建的默认方法,用于设置关键字的着色规则。
addKeyWord(Color color,String... words)-这是开发人员可用于指定需要突出显示的颜色和单词的方法