Java Frage zu Syntax-Highlighter

CPU

Lieutenant
Registriert
Jan. 2006
Beiträge
704
Hallo,

was ich erreichen möchte ist garnicht so viel: es sollen in einem JTextField (!!) alle "." grün angemalt werden (also Textfarbe).

Ich habe also ganz brav gegoogelt und habe eine Klasse gefunden, die schon etwas mit Highlight zutun hat (siehe ganz unten).

Doch: es wird immer nur der Hintergund angemalt. Wie kann ich in der "caretUpdate(...)"-Methode nun die Textfarbe für eine bestimmte Textpassage anders setzen?


Danke vorab,
CPU

Code:
import java.awt.Color;
import java.awt.Font;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Document;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;
import javax.swing.text.DefaultHighlighter.DefaultHighlightPainter;

public class TestHighlightJTextField implements CaretListener {

	/**
	 * The tags returned from the highlighter, used for clearing the current
	 * highlight.
	 */
	Object start, end;

	/** The last highlighter used */
	Highlighter highlighter;

	/** Used to paint good parenthesis matches */
	Highlighter.HighlightPainter goodPainter;

	/** Used to paint bad parenthesis matches */
	Highlighter.HighlightPainter badPainter;

	private DefaultHighlightPainter ext;

	/**
	 * Highlights using a good painter for matched parens, and a bad painter for
	 * unmatched parens
	 */
	TestHighlightJTextField(Highlighter.HighlightPainter goodHighlightPainter,
			Highlighter.HighlightPainter badHighlightPainter) {
		this.goodPainter = goodHighlightPainter;
		this.badPainter = badHighlightPainter;
		
		ext = new DefaultHighlighter.DefaultHighlightPainter(Color.green);
	}

	/** A BracketMatcher with the default highlighters (cyan and magenta) */
	TestHighlightJTextField() {
		this(new DefaultHighlighter.DefaultHighlightPainter(Color.cyan),
				new DefaultHighlighter.DefaultHighlightPainter(Color.magenta));
	}

	public void clearHighlights() {
		if (highlighter != null) {
			if (start != null)
				highlighter.removeHighlight(start);
			if (end != null)
				highlighter.removeHighlight(end);
			start = end = null;
			highlighter = null;
		}
	}

	/** Returns the character at position p in the document */
	public static char getCharAt(Document doc, int p)
			throws BadLocationException {
		return doc.getText(p, 1).charAt(0);
	}

	/**
	 * Returns the position of the matching parenthesis (bracket, whatever) for
	 * the character at paren. It counts all kinds of brackets, so the
	 * "matching" parenthesis might be a bad one. For this demo, we're not going
	 * to take quotes or comments into account since that's not the point.
	 * 
	 * It's assumed that paren is the position of some parenthesis character
	 * 
	 * @return the position of the matching paren, or -1 if none is found
	 **/
	public static int findMatchingParen(Document d, int paren)
			throws BadLocationException {
		int parenCount = 1;
		int i = paren - 1;
		for (; i >= 0; i--) {
			char c = getCharAt(d, i);
			switch (c) {
			case ')':
			case '}':
			case ']':
				parenCount++;
				break;
			case '(':
			case '{':
			case '[':
				parenCount--;
				break;
			}
			if (parenCount == 0)
				break;
		}
		return i;
	}

	/** Called whenever the caret moves, it updates the highlights */
	public void caretUpdate(CaretEvent e) {
		clearHighlights();
		JTextComponent source = (JTextComponent) e.getSource();
		highlighter = source.getHighlighter();
		Document doc = source.getDocument();
		
		// The character we want is the one before the current position
		int closeParen = e.getDot() - 1;
		try {
			char c = getCharAt(doc, closeParen);
			if (c == ')' || c == ']' || c == '}') {
				int openParen = findMatchingParen(doc, closeParen);
				if (openParen >= 0) {
					char c2 = getCharAt(doc, openParen);
					if ((c2 == '(' && c == ')') || (c2 == '{' && c == '}')
							|| (c2 == '[' && c == ']')) {
						start = highlighter.addHighlight(openParen,
								openParen + 1, goodPainter);
						end = highlighter.addHighlight(closeParen,
								closeParen + 1, goodPainter);
					} else {
						start = highlighter.addHighlight(openParen,
								openParen + 1, badPainter);
						end = highlighter.addHighlight(closeParen,
								closeParen + 1, badPainter);
					}
				} else {
					end = highlighter.addHighlight(closeParen, closeParen + 1,
							badPainter);
				}

			}
		} catch (BadLocationException ex) {
			throw new Error(ex);
		}
	}

	/** A demo main */
	public static void main(String a[]) {
		JFrame f = new JFrame();
		JTextField p = new JTextField();
		f.getContentPane().add(new JScrollPane(p));
		p.setFont(new Font("Monospaced", 0, 12));
		p.addCaretListener(new TestHighlightJTextField());
		f.setSize(400, 400);
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.setVisible(true);
	}

}
 
ich habe gerade mal diesen Code hier implementiert:

http://www.java2s.com/Tutorial/Java/0240__Swing/HighLightpainerandJTextField.htm

Und so umgebaut, dass nicht nur das erste Ergebnis, sondern alle markiert werden.

Das ist wohl auch das Stichwort: der Highlighter scheint nur zu markieren und nicht bestimmten Zeichnen eine andere Farbe zu verpassen.

Besser wäre vielleicht ein JEditorPane oder sowas in der Art - hier können z.B. auch RTF-Dokumente angezeigt werden und zwar mit den korrekten Fonts und Farbgebung. Vielleicht hiflt das ja weiter.
 
Man muss es sich nur fest genug wünschen!
Unten der funktionierende Code. Alle Punkte werden rot markiert (aus diesem Artikel: http://forums.sun.com/thread.jspa?forumID=57&threadID=293281).
Aber noch drei Fragen:
1. Könntet Ihr es mal testen und schauen ob's wirklich einwandfrei klappt?
2. Kann ich ein JEditorPane auf 1 Zeile begrenzen?
3. Ich hab' mir das ganze ja zusammengeschustert aus dem Forumbeitrag von Sun. Könnte mir jemand noch einmal genau erklären, wozu ich die for-Schleife nach "startLine"/"endLine" in "processChangedLines" brauche?

CPU

Code:
public class TpHightlight extends DefaultStyledDocument {
	private DefaultStyledDocument doc;
	private Element rootElement;
	private SimpleAttributeSet keyword;
	private SimpleAttributeSet normal;

	public TpHightlight() {
		doc = this;
		rootElement = doc.getDefaultRootElement();

		normal = new SimpleAttributeSet();
		StyleConstants.setForeground(normal, Color.black);

		keyword = new SimpleAttributeSet();
		StyleConstants.setForeground(keyword, Color.red);

	}

	public void insertString(int offset, String str, AttributeSet a)
			throws BadLocationException {
		super.insertString(offset, str, a);
		processChangedLines(offset, str.length());
	}

	public void remove(int offset, int length) throws BadLocationException {
		super.remove(offset, length);
		processChangedLines(offset, 0);
	}

	public void processChangedLines(int offset, int length)
			throws BadLocationException {

		String content = doc.getText(0, doc.getLength());

		int startLine = rootElement.getElementIndex(offset);
		int endLine = rootElement.getElementIndex(offset + length);

		for (int i = startLine; i <= endLine; i++) {

			int startOffset = rootElement.getElement(i).getStartOffset();
			int endOffset = rootElement.getElement(i).getEndOffset() - 1;

			int lineLength = endOffset - startOffset;
			int contentLength = content.length();

			if (endOffset >= contentLength)
				endOffset = contentLength - 1;

			String sub = content;
			ArrayList<Integer> indizies = new ArrayList<Integer>();
			int intofff = 0;

			while (sub.contains(".")) {
				int index = sub.indexOf(".");
				if (index > -1) {
					indizies.add(intofff + index);
					intofff += index + 1;
					sub = sub.substring(index + 1);
				}
			}

			doc.setCharacterAttributes(startOffset, lineLength, normal, true);

			System.out.println(indizies.size());

			System.out.println();

			for (int j = 0; j < indizies.size(); j++) {
				doc.setCharacterAttributes(indizies.get(j), 1, keyword, false);

				System.out.println(indizies.get(j));

			}

			System.out.println("===========================");

		}

	}

	public static void main(String a[]) {

		EditorKit editorKit = new StyledEditorKit() {
			public Document createDefaultDocument() {
				return new TpHightlight();
			}
		};

		final JEditorPane edit = new JEditorPane();
		edit.setEditorKitForContentType("test", editorKit);
		edit.setContentType("test");

		JFrame frame = new JFrame("Syntax Highlighting");
		frame.getContentPane().add(new JScrollPane(edit));
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(800, 300);
		frame.setVisible(true);
	}
}
 
Zurück
Oben