Eigener Syntax Highlighter - Problem

schmidi000

Grünschnabel
Hey Leute, ich habe ein Problem.
Ich hab mir einen eigenen Syntax Highlighter geschrieben, welcher nur zum Teil funktioniert.

Ich hab ein JTextPane auf dem ich den Syntax Highlighter anwende.


Das ist der Thread prüft permanent ob ein Substring im JTextPane mit "<" beginnt und mit ">" endet:

Java:
    class checkForSyntax extends Thread {
        checkForSyntax() {
            setDaemon(true);
            setName("SyntaxChecker");
        }
        
        @Override public void run() {
            while(true) {
                textPaneText = textPane.getText();
                cleanTextPaneText = textPaneText.replaceAll("\r","");
                try {
                            Matcher matcher = Pattern.compile("<.*?>").matcher(cleanTextPaneText);
                            while(matcher.find()) {
                                StyleConstants.setForeground(style,Color.BLUE);
                                doc.setCharacterAttributes(matcher.start(), matcher.end(), textPane.getStyle("Blue"), true);
                            }
                }
                catch(Exception e) {
                    System.err.println("Error while checking syntax!");
                    e.printStackTrace();
                }
            }
        }
    }

Wenn dies der Fall ist wird dieser blau gefärbt.

Hier sind die Initialisierungen und Deklarationen:

Java:
JTextPane textPane = new JTextPane();
public StyledDocument doc = textPane.getStyledDocument();
public Style style = textPane.addStyle("Blue",null);
String textPaneText;

Nun zum Problem:

Wenn ich in mein JTextPane nun einen Text eingebe zb. "<html>" dann wird dieser blau gefärbt, dann mach ich einen Zeilenumbruch mit Enter und gib "</html>" ein, dann wird nur "html>" blau gefärbt. Wenn ich den ganzen Text aus dem JTextPane lösche und schreibe "asdjsnhcfnwevkh" also nichts was im Schlüsselwörter Array vorkommt, dann wird trotzdem alles blau gefärbt.

Beispiel:

Wenn ich zb. schreibe:

<html>
Text
</html>

dann wird "<html>" und "</html>" gefärbt und "Text" nicht, soweit so gut... wenn ich jetzt aber Text bis zum Zeilenanfang lösche, dass das Ganze danach so aussieht:

<html>

</html>

und danach schreibe ich in dieser Zeile, in der vorhin "Text" stand wieder etwas, dann wird der Text auch blau gefärbt.

Ich weiß echt nicht an was das liegt.

mfg schmidi000
 
Zuletzt bearbeitet:

Fabio Hellmann

Erfahrenes Mitglied
Hi und willkommen bei tutorials.de,

der Fehler lieg darin, dass du in dieser Zeile nicht die Position des Endes sondern die Länge des Strings angeben sollst
Java:
doc.setCharacterAttributes(matcher.start(), matcher.end() // HIER muss die Länge des Strings angegeben werden, nicht das Ende
, textPane.getStyle("Blue"), true);

Zudem solltest du auf den DocumentListener gehen und keinen eigenen Thread für die Textüberwachung verwenden.

Ich habe vor einiger Zeit auch einen SyntaxHighlighter geschrieben. Vielleicht hilft dir das ein bischen weiter. ;)
Java:
import java.awt.Color;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;


/**
 * @author fabioh
 * @author $Author$
 * @version $Revision$ $Date$
 */
public class JSyntaxHighlighter extends JTextPane implements DocumentListener
{
	private final Map<Style, Color> syntaxWithColorForHighlighting = new HashMap<Style, Color>();
	
	/**
	 * 
	 */
	public JSyntaxHighlighter() {
		final StyledDocument styledDocument = getStyledDocument();
		styledDocument.addDocumentListener(this);
	}
	
	/**
	 * @param syntax
	 * @param color
	 */
	public void addSyntax(final String syntax, final Color color) {
		final Style style = addStyle(syntax, null);
		syntaxWithColorForHighlighting.put(style, color);
	}
	
	/**
	 * @param syntaxDataMap
	 */
	public void addSyntaxes(final Map<Style, Color> syntaxDataMap) {
		syntaxWithColorForHighlighting.putAll(syntaxDataMap);
	}
	
	/**
	 * @param syntax
	 */
	public void removeSyntax(final String syntax) {
		Style styleToDelete = null;
		for(final Style style : syntaxWithColorForHighlighting.keySet()) {
			if(style.getName().equals(syntax)) {
				styleToDelete = style;
				break;
			}
		}
		syntaxWithColorForHighlighting.remove(styleToDelete);
	}
	
	/**
	 * 
	 */
	public void clearWords() {
		syntaxWithColorForHighlighting.clear();
	}
	
	/*
	 * (non-Javadoc)
	 * @see javax.swing.event.DocumentListener#changedUpdate(javax.swing.event.DocumentEvent)
	 */
	@Override
	public void changedUpdate(final DocumentEvent e) {
	}
	
	/*
	 * (non-Javadoc)
	 * @see javax.swing.event.DocumentListener#insertUpdate(javax.swing.event.DocumentEvent)
	 */
	@Override
	public void insertUpdate(final DocumentEvent e) {
		onSyntaxHighlighting();
	}
	
	/*
	 * (non-Javadoc)
	 * @see javax.swing.event.DocumentListener#removeUpdate(javax.swing.event.DocumentEvent)
	 */
	@Override
	public void removeUpdate(final DocumentEvent e) {
		onSyntaxHighlighting();
	}
	
	private void onSyntaxHighlighting() {
		SwingUtilities.invokeLater(new Runnable()
						{
			@Override
			public void run() {
				final String text = getText().replaceAll("\r", "");
				
				for(final Entry<Style, Color> entry : syntaxWithColorForHighlighting.entrySet()) {
					final Matcher matcher = Pattern.compile(entry.getKey().getName()).matcher(
							text);
					try {
						while(matcher.find()) {
							final int start = matcher.start();
							final int end = matcher.end();
							final int length = end - start;
							StyleConstants.setForeground(entry.getKey(), entry.getValue());
							getStyledDocument().setCharacterAttributes(start, length,
									entry.getKey(), true);
						}
					} catch(final Exception e) {
						System.err.println("Error while checking syntax! " + e.getMessage());
					}
				}
			}
		});
	}
}

So kannst du meinen SyntaxHighlighter ganz einfach testen. :)
Java:
	/**
	 * @param args
	 */
	public static void main(final String[] args) {
		final JFrame f = new JFrame("Syntaxhighlighter");
		f.setSize(400, 400);
		f.setLocationRelativeTo(null);
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		final JSyntaxHighlighter syntaxHighlighter = new JSyntaxHighlighter();
		syntaxHighlighter.addSyntax("<[^>]+.", Color.BLUE); // all Tags
		syntaxHighlighter.addSyntax("error", Color.RED); // only Error-Tags
		f.add(syntaxHighlighter);
		
		f.setVisible(true);
	}

Gruß

Fabio
 
Zuletzt bearbeitet:

schmidi000

Grünschnabel
Hallo Fabio Hellmann,
erstmal danke für deine hilfreiche Antwort, ich hab nämlich nicht daran gedacht es anders als in einem Thread zu machen :D.

Aber bei dem Syntax Highlighter von dir ist leider dasselbe Problem wie bei meinem, nur das der Text (egal ob er zur Syntax gehört oder nicht) erst komplett blau gehighlightet wird wenn man den ganzen Text aus dem JTextPane löscht.

Ich bin leider immer noch nicht dahinter gekommen, wie ich das Problem am besten behandeln kann.

mfg schmidi000

Jawoll, ich habs, ich hab das einfach so gemacht:

Java:
textPane.addSyntax("<{1}.*[^<>]>{1}", Color.BLUE);
textPane.addSyntax(".*[^<>]", Color.BLACK);

also jeder Text indem nicht "<" und ">" vorkommt wird schwarz gehiglightet.

Danke nochmal! ;D

mfg