2012-10-25 12 views
9

Ich habe eine Zeit lang für diese Suche und so weit alles, was ich habe in der Lage gewesen, mit zu kommen, wie man einen Stil zu schaffen und es zu einem Zeichen gilt wie folgt:Wie kann ich jedes Zeichen in einem JTextPane auf eine andere Farbe/Hintergrundfarbe einstellen?

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); 

Dies ist nützlich, wenn Sie in Ihrem Dokument nur wenige Stile haben und diese nach Namen speichern möchten, damit Sie sie später problemlos anwenden können. In meiner Anwendung möchte ich die Vordergrundfarbe (eine von nur wenigen Werten) und die Hintergrundfarbe (Graustufen, viele verschiedene Werte) unabhängig für jedes Zeichen im Text einstellen können. Es scheint eine riesige Verschwendung zu sein, potentiell Hunderte/Tausende verschiedener Stile dafür zu schaffen. Gibt es eine Möglichkeit, diese Attribute festzulegen, ohne jedes Mal einen neuen Stil erstellen zu müssen? Es wäre viel einfacher, wenn ich nur den Text rendern müsste, aber ich muss es auch editierbar machen. Gibt es eine Möglichkeit, dies mit JTextPane zu tun, oder gibt es eine andere Swing-Klasse, die diese Funktionalität bietet?

Antwort

14

Wenn Sie den Stil für jedes Zeichen ändern möchten In einer Texttafel gibt es hier einen völlig zufälligen Weg. Sie erstellen für jedes Zeichen ein anderes Attributset. Bis zu Ihnen, um passende Kombination zu finden (Vordergrund-/Hintergrundkontrast, nicht zu großer Unterschied in der Größe der Zeichen, usw.). Sie können auch die verschiedenen Stile speichern, die Sie bereits angewendet haben, damit Sie sie nicht zweimal verwenden.

enter image description here

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(); 
      } 
     }); 
    } 

} 
+0

Copyright-Problem mit dem Text? Würde es gerne in SwingX-Test-Utils verwenden :-) – kleopatra

+0

@kleopatra AFAIK "Lorem ipsum" ist seit über 500 Jahren in der Öffentlichkeit. –

+1

@kleopatra nein Ich nahm es von [hier] (http://www.lipsum.com/) –

9

Ich bin mir nicht sicher, was du meinst, aber man kann nicht eine Schleife durch jedes Zeichen in der JtextPane und innerhalb dieser Schleife durchlaufen alle Buchstaben/Zeichen, die Sie hervorheben möchten usw. Haben sie eine wenn Aussage den Charakter prüft und dann Stellen Sie die Style entsprechend ein. Hier

ist ein Beispiel, das ich habe ich umgesetzt es nur für die Zeichen h und w zu Demonstrationszwecken:

enter image description here

//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); 
    } 
} 
+0

Danke David. Es ist kein großes Problem, jedes Zeichen einzeln zu setzen. Es ist nur so, dass jedes Zeichen ein neuer Stil sein muss, der wahrscheinlich nicht mit anderen Charakteren geteilt wird. Ich muss das für mehrere tausend Zeichen tun und werde wahrscheinlich Hunderte von Stilen brauchen. Ich möchte das nur tun, ohne jedes Mal einen neuen benannten Stil hinzufügen zu müssen. Es wird jedoch nur eine von einigen Vordergrundfarben geben, also könnte ich den Text über einen Hintergrund legen, den ich selbst rende. – JaredL

0

Ich denke, der beste Weg, dies zu tun haben, ist, wie wir in Editoren mit Highlight, nicht für Zeichen stürmte, aber mit einem Muster, zum Beispiel:

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