texto letra example definicion componentes color cambiar agregar java swing jtextpane

java - letra - jtextpane example



¿Cómo cambiar el color de palabras específicas en un JTextPane? (4)

No. No debes anular el método paintComponent (). En su lugar, debe usar StyledDocument . También debe delimitar las palabras por su cuenta.

Aquí está la demostración, que convierte "público", "protegido" y "privado" en rojo cuando se escribe, como un simple editor de código:

import javax.swing.*; import java.awt.*; import javax.swing.text.*; public class Test extends JFrame { private int findLastNonWordChar (String text, int index) { while (--index >= 0) { if (String.valueOf(text.charAt(index)).matches("//W")) { break; } } return index; } private int findFirstNonWordChar (String text, int index) { while (index < text.length()) { if (String.valueOf(text.charAt(index)).matches("//W")) { break; } index++; } return index; } public Test () { setDefaultCloseOperation(EXIT_ON_CLOSE); setSize(400, 400); setLocationRelativeTo(null); final StyleContext cont = StyleContext.getDefaultStyleContext(); final AttributeSet attr = cont.addAttribute(cont.getEmptySet(), StyleConstants.Foreground, Color.RED); final AttributeSet attrBlack = cont.addAttribute(cont.getEmptySet(), StyleConstants.Foreground, Color.BLACK); DefaultStyledDocument doc = new DefaultStyledDocument() { public void insertString (int offset, String str, AttributeSet a) throws BadLocationException { super.insertString(offset, str, a); String text = getText(0, getLength()); int before = findLastNonWordChar(text, offset); if (before < 0) before = 0; int after = findFirstNonWordChar(text, offset + str.length()); int wordL = before; int wordR = before; while (wordR <= after) { if (wordR == after || String.valueOf(text.charAt(wordR)).matches("//W")) { if (text.substring(wordL, wordR).matches("(//W)*(private|public|protected)")) setCharacterAttributes(wordL, wordR - wordL, attr, false); else setCharacterAttributes(wordL, wordR - wordL, attrBlack, false); wordL = wordR; } wordR++; } } public void remove (int offs, int len) throws BadLocationException { super.remove(offs, len); String text = getText(0, getLength()); int before = findLastNonWordChar(text, offs); if (before < 0) before = 0; int after = findFirstNonWordChar(text, offs); if (text.substring(before, after).matches("(//W)*(private|public|protected)")) { setCharacterAttributes(before, after - before, attr, false); } else { setCharacterAttributes(before, after - before, attrBlack, false); } } }; JTextPane txt = new JTextPane(doc); txt.setText("public class Hi {}"); add(new JScrollPane(txt)); setVisible(true); } public static void main (String args[]) { new Test(); } }

El código no es tan hermoso ya que lo escribí rápidamente, pero funciona. Y espero que te dé una pista.

¿Cómo cambio el color de palabras específicas en un JTextPane solo mientras el usuario está escribiendo? ¿Debo anular el método JTextPane paintComponent ?


Otra solución es usar un DocumentFilter .

Aquí hay un ejemplo:

Crea una clase que amplíe DocumentFilter:

private final class CustomDocumentFilter extends DocumentFilter { private final StyledDocument styledDocument = yourTextPane.getStyledDocument(); private final StyleContext styleContext = StyleContext.getDefaultStyleContext(); private final AttributeSet greenAttributeSet = styleContext.addAttribute(styleContext.getEmptySet(), StyleConstants.Foreground, Color.GREEN); private final AttributeSet blackAttributeSet = styleContext.addAttribute(styleContext.getEmptySet(), StyleConstants.Foreground, Color.BLACK); // Use a regular expression to find the words you are looking for Pattern pattern = buildPattern(); @Override public void insertString(FilterBypass fb, int offset, String text, AttributeSet attributeSet) throws BadLocationException { super.insertString(fb, offset, text, attributeSet); handleTextChanged(); } @Override public void remove(FilterBypass fb, int offset, int length) throws BadLocationException { super.remove(fb, offset, length); handleTextChanged(); } @Override public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attributeSet) throws BadLocationException { super.replace(fb, offset, length, text, attributeSet); handleTextChanged(); } /** * Runs your updates later, not during the event notification. */ private void handleTextChanged() { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { updateTextStyles(); } }); } /** * Build the regular expression that looks for the whole word of each word that you wish to find. The "//b" is the beginning or end of a word boundary. The "|" is a regex "or" operator. * @return */ private Pattern buildPattern() { StringBuilder sb = new StringBuilder(); for (String token : ALL_WORDS_THAT_YOU_WANT_TO_FIND) { sb.append("//b"); // Start of word boundary sb.append(token); sb.append("//b|"); // End of word boundary and an or for the next word } if (sb.length() > 0) { sb.deleteCharAt(sb.length() - 1); // Remove the trailing "|" } Pattern p = Pattern.compile(sb.toString()); return p; } private void updateTextStyles() { // Clear existing styles styledDocument.setCharacterAttributes(0, yourTextPane.getText().length(), blackAttributeSet, true); // Look for tokens and highlight them Matcher matcher = pattern.matcher(yourTextPane.getText()); while (matcher.find()) { // Change the color of recognized tokens styledDocument.setCharacterAttributes(matcher.start(), matcher.end() - matcher.start(), greenAttributeSet, false); } } }

Todo lo que necesita hacer entonces es aplicar el DocumentFilter que creó a su JTextPane siguiente manera:

((AbstractDocument) yourTextPane.getDocument()).setDocumentFilter(new CustomDocumentFilter());


Puede extender DefaultStyledDocument como lo hice aquí para un editor de SQL que estoy construyendo con coloreado de texto de palabra clave ...

import java.util.ArrayList; import java.util.List; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.DefaultStyledDocument; import javax.swing.text.Style; public class KeywordStyledDocument extends DefaultStyledDocument { private static final long serialVersionUID = 1L; private Style _defaultStyle; private Style _cwStyle; public KeywordStyledDocument(Style defaultStyle, Style cwStyle) { _defaultStyle = defaultStyle; _cwStyle = cwStyle; } public void insertString (int offset, String str, AttributeSet a) throws BadLocationException { super.insertString(offset, str, a); refreshDocument(); } public void remove (int offs, int len) throws BadLocationException { super.remove(offs, len); refreshDocument(); } private synchronized void refreshDocument() throws BadLocationException { String text = getText(0, getLength()); final List<HiliteWord> list = processWords(text); setCharacterAttributes(0, text.length(), _defaultStyle, true); for(HiliteWord word : list) { int p0 = word._position; setCharacterAttributes(p0, word._word.length(), _cwStyle, true); } } private static List<HiliteWord> processWords(String content) { content += " "; List<HiliteWord> hiliteWords = new ArrayList<HiliteWord>(); int lastWhitespacePosition = 0; String word = ""; char[] data = content.toCharArray(); for(int index=0; index < data.length; index++) { char ch = data[index]; if(!(Character.isLetter(ch) || Character.isDigit(ch) || ch == ''_'')) { lastWhitespacePosition = index; if(word.length() > 0) { if(isReservedWord(word)) { hiliteWords.add(new HiliteWord(word,(lastWhitespacePosition - word.length()))); } word=""; } } else { word += ch; } } return hiliteWords; } private static final boolean isReservedWord(String word) { return(word.toUpperCase().trim().equals("CROSS") || word.toUpperCase().trim().equals("CURRENT_DATE") || word.toUpperCase().trim().equals("CURRENT_TIME") || word.toUpperCase().trim().equals("CURRENT_TIMESTAMP") || word.toUpperCase().trim().equals("DISTINCT") || word.toUpperCase().trim().equals("EXCEPT") || word.toUpperCase().trim().equals("EXISTS") || word.toUpperCase().trim().equals("FALSE") || word.toUpperCase().trim().equals("FETCH") || word.toUpperCase().trim().equals("FOR") || word.toUpperCase().trim().equals("FROM") || word.toUpperCase().trim().equals("FULL") || word.toUpperCase().trim().equals("GROUP") || word.toUpperCase().trim().equals("HAVING") || word.toUpperCase().trim().equals("INNER") || word.toUpperCase().trim().equals("INTERSECT") || word.toUpperCase().trim().equals("IS") || word.toUpperCase().trim().equals("JOIN") || word.toUpperCase().trim().equals("LIKE") || word.toUpperCase().trim().equals("LIMIT") || word.toUpperCase().trim().equals("MINUS") || word.toUpperCase().trim().equals("NATURAL") || word.toUpperCase().trim().equals("NOT") || word.toUpperCase().trim().equals("NULL") || word.toUpperCase().trim().equals("OFFSET") || word.toUpperCase().trim().equals("ON") || word.toUpperCase().trim().equals("ORDER") || word.toUpperCase().trim().equals("PRIMARY") || word.toUpperCase().trim().equals("ROWNUM") || word.toUpperCase().trim().equals("SELECT") || word.toUpperCase().trim().equals("SYSDATE") || word.toUpperCase().trim().equals("SYSTIME") || word.toUpperCase().trim().equals("SYSTIMESTAMP") || word.toUpperCase().trim().equals("TODAY") || word.toUpperCase().trim().equals("TRUE") || word.toUpperCase().trim().equals("UNION") || word.toUpperCase().trim().equals("UNIQUE") || word.toUpperCase().trim().equals("WHERE")); } }

Simplemente agréguelo a su clase de la siguiente manera:

import java.awt.BorderLayout; import java.awt.Color; import java.awt.Font; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTextPane; import javax.swing.text.BadLocationException; import javax.swing.text.Style; import javax.swing.text.StyleConstants; import javax.swing.text.StyleContext; public class SQLEditor extends JFrame { private static final long serialVersionUID = 1L; public SQLEditor() { StyleContext styleContext = new StyleContext(); Style defaultStyle = styleContext.getStyle(StyleContext.DEFAULT_STYLE); Style cwStyle = styleContext.addStyle("ConstantWidth", null); StyleConstants.setForeground(cwStyle, Color.BLUE); StyleConstants.setBold(cwStyle, true); final JTextPane pane = new JTextPane(new KeywordStyledDocument(defaultStyle, cwStyle)); pane.setFont(new Font("Courier New", Font.PLAIN, 12)); JScrollPane scrollPane = new JScrollPane(pane); getContentPane().add(scrollPane, BorderLayout.CENTER); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(375, 400); } public static void main(String[] args) throws BadLocationException { SQLEditor app = new SQLEditor(); app.setVisible(true); } }

Aquí está la clase de HiliteWord que falta ...

public class HiliteWord { int _position; String _word; public HiliteWord(String word, int position) { _position = position; _word = word; } }


Sobrescribir paintComponent no lo ayudará.

Esto no es fácil, pero tampoco imposible. Algo como esto te ayudará a:

DefaultStyledDocument document = new DefaultStyledDocument(); JTextPane textpane = new JTextPane(document); StyleContext context = new StyleContext(); // build a style Style style = context.addStyle("test", null); // set some style properties StyleConstants.setForeground(style, Color.BLUE); // add some data to the document document.insertString(0, "", style);

Es posible que deba modificar esto, pero al menos le muestra por dónde empezar.