2012-10-25 11 views
9

Szukałem tego przez jakiś czas i do tej pory wszystko udało mi się wymyślić sposób, aby utworzyć styl i zastosować go do charakteru tak:Jak ustawić każdy znak na inny kolor/kolor tła w 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); 

Jest to użyteczne jeśli masz tylko kilka stylów w swoim dokumencie i chcesz przechowywać je po nazwie, aby móc je później łatwo zastosować. W mojej aplikacji chcę móc ustawić kolor pierwszego planu (jedną z niewielu wartości) i kolor tła (skala szarości, wiele różnych wartości) niezależnie dla każdego znaku w tekście. Wygląda na to, że ogromne marnotrawstwo tworzy potencjalnie setki/tysiące różnych stylów. Czy istnieje sposób ustawiania tych atrybutów bez konieczności tworzenia nowego stylu za każdym razem? Byłoby o wiele łatwiej, gdybym tylko musiał renderować tekst, ale muszę go również edytować. Czy jest jakiś sposób, aby to zrobić z JTextPane, czy istnieje inna klasa swing, która oferuje tę funkcjonalność?

Odpowiedz

14

Jeśli chcesz zmienić styl dla każdego znaku w tekście jest tu kompletny losowy sposób na zrobienie tego. Tworzysz inny zestaw atrybutów dla każdej postaci. Do ciebie, aby znaleźć odpowiednią kombinację (kontrast pierwszego planu/tła, niezbyt duża różnica w wielkości znaków itp.). Możesz także przechowywać różne style, które już zastosowałeś, aby nie używać tego samego dwa razy.

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

ewentualne naruszenie praw autorskich do tekstu? Chciałbym go użyć w testach SwingX :-) – kleopatra

+0

@kleopatra AFAIK "Lorem ipsum" jest w domenie publicznej, ponieważ istnieje ponad 500 lat. –

+1

@kleopatra nie Wziąłem go od [tutaj] (http://www.lipsum.com/) –

9

Nie jestem pewien co masz na myśli, ale nie można pętli każdego znaku w JtextPane i wewnątrz tej pętli iterację wszystkich liter/znaków chcesz wyróżnić itd. Masz jeśli oświadczenie sprawdzanie znaku, a następnie odpowiednio ustawić Style.

Oto przykład zrobiłem ja tylko wprowadziły go do bohaterów h i w dla celów demonstracyjnych:

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

Dzięki David. Ustawienie każdego znaku indywidualnie nie jest zbyt dużym problemem, po prostu każda postać musi być nowym stylem, który prawdopodobnie nie jest dzielony z żadnymi innymi postaciami. Muszę to zrobić dla kilku tysięcy znaków, więc prawdopodobnie będę potrzebował setek stylów. Chciałbym to zrobić bez konieczności dodawania nowego nazwanego stylu za każdym razem. Będzie tylko jeden z kilku kolorów na pierwszym planie, więc myślę, że mógłbym umieścić tekst na tle, który sam sobie wyrenderuję. – JaredL

0

Myślę, że najlepszym sposobem, trzeba to zrobić, to jak mamy w redakcji z podświetleniem, nie goni za bohaterów, ale o wzór, na przykład:

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); 
} 
Powiązane problemy