2012-10-25 29 views
9

Ho cercato per questo per un po 'e finora tutto quello che ho potuto venire in mente è come creare uno stile e applicarlo a un personaggio in questo modo:Come posso impostare ciascun carattere su un colore diverso/colore di sfondo in un JTextPane?

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

Questo è utile se nel documento sono presenti solo pochi stili e si desidera memorizzarli per nome in modo da poterli applicare facilmente in seguito. Nella mia applicazione voglio essere in grado di impostare il colore di primo piano (uno dei pochi valori) e il colore di sfondo (scala di grigi, molti valori diversi) indipendentemente per ogni carattere nel testo. Sembra un enorme spreco creare potenzialmente centinaia/migliaia di stili differenti per questo. C'è un modo per impostare questi attributi senza dover creare un nuovo stile ogni volta? Sarebbe molto più semplice se dovessi solo rendere il testo, ma ho anche bisogno di renderlo modificabile. C'è un modo per farlo con JTextPane, o c'è un'altra classe swing che offre questa funzionalità?

risposta

14

Se si vuole cambiare lo stile per ogni personaggio in un testo, ecco un modo completamente casuale per farlo. Si crea un set di attributi diverso per ciascun carattere. Fino a te per trovare la combinazione appropriata (contrasto in primo piano/sfondo, non troppa differenza nelle dimensioni dei caratteri, ecc ...). Puoi anche memorizzare i diversi stili che hai già applicato in modo da non utilizzare lo stesso due volte.

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

eventuali problemi di copyright con il testo? Mi piacerebbe usarlo nei programmi di prova SwingX :-) – kleopatra

+0

@kleopatra AFAIK "Lorem ipsum" è di dominio pubblico poiché esiste da oltre 500 anni. –

+1

@kleopatra no L'ho preso da [qui] (http://www.lipsum.com/) –

9

io non sono sicuro di quello che vuoi dire, ma non puoi ciclo attraverso ogni carattere nel JtextPane e all'interno di tale iterare ciclo attraverso tutte le lettere/caratteri che si desidera evidenziare ecc Hai un se dichiarazione controllare il carattere e poi impostare il Style di conseguenza.

Ecco un esempio che ho fatto ho implementato solo per i personaggi h e w a scopo dimostrativo:

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

Grazie David. Impostare individualmente ciascun personaggio non è un problema, è solo che ogni personaggio deve essere un nuovo stile che probabilmente non è condiviso con nessun altro personaggio. Ho bisogno di farlo per diverse migliaia di caratteri e quindi probabilmente avrà bisogno di centinaia di stili. Mi piacerebbe farlo senza dover aggiungere un nuovo stile nominato ogni volta. Tuttavia, ci sarà solo uno dei pochi colori in primo piano, quindi credo che potrei mettere il testo su uno sfondo che mi restituisco. – JaredL

0

Penso che il modo migliore che devi fare questo è come abbiamo in redazione con illuminazione, non inseguire per i caratteri, ma avere un modello, per esempio:

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