JEditorPane mit Zeilenhervorhebung
7. Februar 2009 von Jan in Java, Java Code Beispiele
Schlagwörter:Java, SQL, Sun
Ich habe für meinen Editor eine Möglichkeit gesucht die aktuelle Zeile unter dem Cursor vollständig mit einer anderen Hintergrundfarbe hervorzuheben. Diese Möglichkeit habe ich folgendermassen realisiert:
Zusammenfassung:
Der JEditorPane füge ich einen speziellen CaretListener hinzu der bei Veränderungen des Cursors einen wiederum für die aktuelle Zeile einen Highlighter einrichtet. Das besondere ist der als innere Klasse realisierte HightlighterPainter. Dieser ist so entwickelt, dass er die ganze Zeile unabhängig von der Zeichenanzahl also auf die sichtbare Breite des Editors hervorhebt.
Hier nun der Quelltext des CaretListeners:
package sqlrunner.text; import java.awt.Color; import java.awt.Graphics; import java.awt.Rectangle; import java.awt.Shape; import javax.swing.event.CaretEvent; import javax.swing.event.CaretListener; import javax.swing.plaf.TextUI; import javax.swing.text.BadLocationException; import javax.swing.text.Element; import javax.swing.text.Highlighter; import javax.swing.text.JTextComponent; import javax.swing.text.LayeredHighlighter; import javax.swing.text.Position; import javax.swing.text.Utilities; import javax.swing.text.View; public class HighlightCurrentLineCaretListener implements CaretListener { static final Color DEFAULT_COLOR = new Color(230, 230, 250); private Highlighter.HighlightPainter painter; private Object highlight; public HighlightCurrentLineCaretListener() { this(null); } public HighlightCurrentLineCaretListener(Color highlightColor) { Color c = highlightColor != null ? highlightColor : DEFAULT_COLOR; this.painter = new LineHighlightPainter(c); } public void caretUpdate(CaretEvent evt) { final JTextComponent comp = (JTextComponent) evt.getSource(); if (comp != null && this.highlight != null) { comp.getHighlighter().removeHighlight(this.highlight); this.highlight = null; } int pos = comp.getCaretPosition(); final Element elem = Utilities.getParagraphElement(comp, pos); int start = elem.getStartOffset(); int end = elem.getEndOffset(); try { this.highlight = comp.getHighlighter().addHighlight(start, end, this.painter); comp.repaint(); } catch (BadLocationException ex) { ex.printStackTrace(); } } /** * Simple highlight painter that fills a highlighted area with * a solid color. */ public static class LineHighlightPainter extends LayeredHighlighter.LayerPainter { private Color color; /** * Constructs a new highlight painter. If <code>c</code> is null, * the JTextComponent will be queried for its selection color. * * @param c * the color for the highlight */ public LineHighlightPainter(Color c) { this.color = c; } /** * Returns the color of the highlight. * * @return the color */ public Color getColor() { return this.color; } // --- HighlightPainter methods --------------------------------------- /** * Paints a highlight. * * @param g * the graphics context * @param offs0 * the starting model offset >= 0 * @param offs1 * the ending model offset >= offs1 * @param bounds * the bounding box for the highlight * @param c * the editor */ public void paint(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c) { final Rectangle alloc = bounds.getBounds(); try { // --- determine locations --- TextUI mapper = c.getUI(); final Rectangle p0 = mapper.modelToView(c, offs0); final Rectangle p1 = mapper.modelToView(c, offs1); // --- render --- if (getColor() == null) { g.setColor(c.getSelectionColor()); } else { g.setColor(getColor()); } final Rectangle r = p0.union(p1); g.fillRect(r.x, r.y, r.width, r.height); } catch (BadLocationException e) { // can't render } } // --- LayerPainter methods ---------------------------- /** * Paints a portion of a highlight. * * @param g * the graphics context * @param offs0 * the starting model offset >= 0 * @param offs1 * the ending model offset >= offs1 * @param bounds * the bounding box of the view, which is not * necessarily the region to paint. * @param c * the editor * @param view * View painting for * @return region drawing occured in */ @Override public Shape paintLayer(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c, View view) { if (getColor() == null) { g.setColor(c.getSelectionColor()); } else { g.setColor(getColor()); } // Should only render part of View. try { // --- determine locations --- Shape shape = view.modelToView( offs0, Position.Bias.Forward, offs1, Position.Bias.Backward, bounds); Rectangle r = shape instanceof Rectangle ? (Rectangle) shape : shape.getBounds(); g.fillRect(r.x, r.y, c.getWidth(), r.height); return r; } catch (BadLocationException e) { // can't render } return null; } } }
Diesen CaretListener muss man nun mit:
textComp.addCaretListener(new HighlightCurrentLineCaretListener());
der Textkomponente hinzufügen. Hat bei mir ausgezeichnet funktioniert. Ich habe diesen Code unter Mac OS X und Windows getestet und er läuft abwärts bis Java 5.
- Kommentare deaktiviert