问题
I've been searching for this for a while and so far all I've been able to come up with is how to create a style and apply it to a character like so:
StyledDocument doc = (StyledDocument) new DefaultStyledDocument();
JTextPane textpane = new JTextPane(doc);
textpane.setText("Test");
javax.swing.text.Style style = textpane.addStyle("Red", null);
StyleConstants.setForeground(style, Color.RED);
doc.setCharacterAttributes(0, 1, textpane.getStyle("Red"), true);
This is useful if you have only a few styles in your document and want to store them by name so that you can apply them easily later on. In my application I want to be able to set the foreground color (one of only a few values) and the background color (grayscale, many different values) independently for every character in the text. It seems like a huge waste to create potentially hundreds/thousands of different styles for this. Is there a way to set these attributes without having to create a new style each time? It would be much easier if I only had to render the text but I also need to make it editable as well. Is there a way to do this with JTextPane
, or is there another swing class that offers this functionality?
回答1:
If you want to change the style for each character in a textpane, here is a complete random way to do it. You create a different attribute set for each character. Up to you to find appropriate combination (foreground/background contrast, not too much difference in size of the chars, etc...). You could also store the different styles you have already applied so that you don't use the same one twice.
import java.awt.Color;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class TestDifferentStyles {
private void initUI() {
JFrame frame = new JFrame(TestDifferentStyles.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
StyledDocument doc = new DefaultStyledDocument();
JTextPane textPane = new JTextPane(doc);
textPane.setText("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has "
+ "been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of "
+ "type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the "
+ "leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the"
+ " release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing "
+ "software like Aldus PageMaker including versions of Lorem Ipsum.");
Random random = new Random();
for (int i = 0; i < textPane.getDocument().getLength(); i++) {
SimpleAttributeSet set = new SimpleAttributeSet();
// StyleConstants.setBackground(set, new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256)));
StyleConstants.setForeground(set, new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256)));
StyleConstants.setFontSize(set, random.nextInt(12) + 12);
StyleConstants.setBold(set, random.nextBoolean());
StyleConstants.setItalic(set, random.nextBoolean());
StyleConstants.setUnderline(set, random.nextBoolean());
doc.setCharacterAttributes(i, 1, set, true);
}
frame.add(new JScrollPane(textPane));
frame.setSize(500, 400);
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new TestDifferentStyles().initUI();
}
});
}
}
回答2:
I'm not sure what you mean, but cant you loop through each character in the JtextPane
and within that loop iterate through all letters/characters you want to highlight etc. Have an if statement checking the character and then set the Style
accordingly.
Here is an example I made I only implemented it for the characters h and w for demonstration purposes:
//necessary imports
import java.awt.Color;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class Test {
/**
* Default constructor for Test.class
*/
public Test() {
initComponents();
}
public static void main(String[] args) {
/**
* Create GUI and components on Event-Dispatch-Thread
*/
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Test test = new Test();
}
});
}
/**
* Initialize GUI and components (including ActionListeners etc)
*/
private void initComponents() {
JFrame jFrame = new JFrame();
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
StyledDocument doc = (StyledDocument) new DefaultStyledDocument();
JTextPane textPane = new JTextPane(doc);
textPane.setText("Hello, world! :)");
//create necessary styles for various characters
javax.swing.text.Style style = textPane.addStyle("Red", null);
StyleConstants.setForeground(style, Color.RED);
javax.swing.text.Style style2 = textPane.addStyle("Blue", null);
StyleConstants.setForeground(style2, Color.BLUE);
//create array of characters to check for and style
String[] lettersToEdit = new String[]{"h", "w"};
//create arraylist to hold each character in textPane
ArrayList<String> strings = new ArrayList<>();
//get all text
String text = textPane.getText();
//populate arraylist
for (int i = 0; i < text.length(); i++) {
strings.add(text.charAt(i) + "");
}
//declare variabe to hold position
int position = 0;
for (String s1 : strings) {//for each character in the textpane text
for (String s2 : lettersToEdit) {//for each character in array to check (lettersToEdit)
if (s2.toLowerCase().equalsIgnoreCase(s1)) {//if there was a match
System.out.println("found a match: " + s1);
System.out.println("counter: " + position + "/" + (position + 1));
//check which chacacter we matched
if (s1.equalsIgnoreCase(lettersToEdit[0])) {
//set appropriate style
doc.setCharacterAttributes(position, 1, textPane.getStyle("Red"), true);
}
if (s1.equalsIgnoreCase(lettersToEdit[1])) {
doc.setCharacterAttributes(position, 1, textPane.getStyle("Blue"), true);
}
}
}
//increase position after each character on textPane is parsed
position++;
}
jFrame.add(textPane);
//pack frame (size JFrame to match preferred sizes of added components and set visible
jFrame.pack();
jFrame.setVisible(true);
}
}
回答3:
I think the best way you have to do this is like we have in editors with highlight, not chasing for characters, but having a pattern, for instance:
private static HashMap<Pattern, Color> patternColors;
private static String GENERIC_XML_NAME = "[A-Za-z]+[A-Za-z0-9\\-_]*(:[A-Za-z]+[A-Za-z0-9\\-_]+)?";
private static String TAG_PATTERN = "(</?" + GENERIC_XML_NAME + ")";
private static String TAG_END_PATTERN = "(>|/>)";
private static String TAG_ATTRIBUTE_PATTERN = "(" + GENERIC_XML_NAME + ")\\w*\\=";
private static String TAG_ATTRIBUTE_VALUE = "\\w*\\=\\w*(\"[^\"]*\")";
private static String TAG_COMMENT = "(<\\!--[\\w ]*-->)";
private static String TAG_CDATA = "(<\\!\\[CDATA\\[.*\\]\\]>)";
private static final Color COLOR_OCEAN_GREEN = new Color(63, 127, 127);
private static final Color COLOR_WEB_BLUE = new Color(0, 166, 255);
private static final Color COLOR_PINK = new Color(127, 0, 127);
static {
// NOTE: the order is important!
patternColors = new LinkedHashMap<Pattern, Color>();
patternColors.put(Pattern.compile(TAG_PATTERN), Color.BLUE); // COLOR_OCEAN_GREEN | Color.BLUE
patternColors.put(Pattern.compile(TAG_CDATA), COLOR_WEB_BLUE);
patternColors.put(Pattern.compile(TAG_ATTRIBUTE_PATTERN), COLOR_PINK);
patternColors.put(Pattern.compile(TAG_END_PATTERN), COLOR_OCEAN_GREEN);
patternColors.put(Pattern.compile(TAG_COMMENT), Color.GRAY);
patternColors.put(Pattern.compile(TAG_ATTRIBUTE_VALUE), COLOR_OCEAN_GREEN); //Color.BLUE | COLOR_OCEAN_GREEN
}
public XmlView(Element element) {
super(element);
// Set tabsize to 4 (instead of the default 8).
getDocument().putProperty(PlainDocument.tabSizeAttribute, 4);
}
来源:https://stackoverflow.com/questions/13074428/how-can-i-set-each-character-to-a-different-color-background-color-in-a-jtextpan