Reputation: 301
I have JTextPane in JFrame where I will type my SQL queries, while typing I want to show the different keyword text in my own defined font color which has to show dynamically.
For example: If I type as below
SELECT * FROM TABLE WHERE 1=1;
I need different color for each keyword which has to be update dynamically in JTextPane while I am typing. Like below
SELECT --> red color
FROM --> white color
WHERE --> green color
Please provide with simple solution to achieve my above scenario, thanks in advance
Upvotes: 2
Views: 82
Reputation: 4188
Not optimal, but I came up with a solution that first removes the whole text from the pane and then replaces it, going through each word and using StyleContext
& AttributeSet
to change the color if the word matches a certain string from a HashMap
.
Output:
Code:
import java.awt.Color;
import java.awt.EventQueue;
import java.util.HashMap;
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
public class Example {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new Example();
}
});
}
public Example() {
JFrame frame = new JFrame();
MyTextPane textPane = new MyTextPane();
textPane.getColoredWordsMap().put("SELECT", Color.RED);
textPane.getColoredWordsMap().put("FROM", Color.WHITE);
textPane.getColoredWordsMap().put("WHERE", Color.GREEN);
frame.getContentPane().add(textPane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private class MyTextPane extends JTextPane {
private boolean human = true;
private HashMap<String, Color> coloredWordsMap = new HashMap<String, Color>();
public MyTextPane() {
setBackground(Color.GRAY);
getDocument().addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent e) {
updateText();
}
@Override
public void insertUpdate(DocumentEvent e) {
updateText();
}
@Override
public void removeUpdate(DocumentEvent e) {
updateText();
}
});
}
private void updateText() {
if (human) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
human = false;
JTextPane textPane = MyTextPane.this;
boolean spaceBar = false;
if (textPane.getText().length() > 0
&& textPane.getText().substring(textPane.getText().length() - 1).equals(" ")) {
spaceBar = true;
}
String[] words = textPane.getText().split(" ");
textPane.setText("");
for (String word : words) {
// This is not a mistake. The .equals method would
// just compare the content of the strings.
String toAppend = (words[words.length - 1] == (word)) ? "" : " ";
boolean colored = false;
for (String coloredWord : getColoredWordsMap().keySet()) {
if (word.equals(coloredWord)) {
append(word + toAppend, getColoredWordsMap().get(coloredWord));
colored = true;
}
}
if (!colored) {
append(word + toAppend, Color.BLACK);
}
}
if (spaceBar) {
append(" ", Color.BLACK);
}
human = true;
}
});
}
}
private void append(String text, Color color) {
JTextPane textPane = MyTextPane.this;
StyleContext sc = StyleContext.getDefaultStyleContext();
AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, color);
int length = textPane.getDocument().getLength();
textPane.setCaretPosition(length);
textPane.setCharacterAttributes(aset, false);
textPane.replaceSelection(text);
}
public HashMap<String, Color> getColoredWordsMap() {
return coloredWordsMap;
}
}
}
Upvotes: 3