Aktuelle Zeile in JTextPane farblich hervorheben

preachie

Aktives Mitglied
Hallo zusammen,

ich versuche nun mittlerweile seit fast 2 Tagen eine Anforderung an ein Editorfenster in den Griff zu bekommen... leider bislang vergeblich :(

Zielsetzung ist, dass ich ein Text-Editor/Eingabefenster habe, in dem die gesamte, aktuelle Zeile farblich hervorgehoben ist, wie man es von gängigen Texteditoren her kennt.
Mit "aktueller" Zeile ist die Zeile gemeint, in der sich aktuell der Cursor, bzw. besser gesagt der/die/das??? Caret.

Über Google habe ich 2 Ansätze gefunden, bei denen ich es aber leider nicht schaffe, sie korrekt umzusetzen.

Der erste Ansatz verfolgt den Weg den DefaultHighlighter zu überschreiben (Custom Highligth in JEditorPanel
Java:
 [line] [word] [highlight] [jeditorpanel][/url]). Bei dem zweiten Ansatz wird stattdessen der HighlighterPainter überschrieben ([url=http://www.jroller.com/santhosh/date/20050622]Santhosh Kumar's Weblog : <a href="https://myswing.dev.java.net/MyBlog/MySwingTree.html">Santhosh Kumar's Weblog</a>[/url]).

Aktuell versuche ich mich noch immer am ersten Ansatz, der aber wie gesagt nicht so funktioniert wie gewünscht.

Am Ende des Beitrags poste ich dann noch ein kleines Programmbeispiel.
Dieses verhält sich wie folgt:
- Wenn ich das Programm starte, befindet sich der Cursor aktiv in der ersten Zeile des JTextPane. Die Zeile ist jedoch nicht highlighted
- Tippe ich beliebige Zeichen ein, so werden diese farblich hinterlegt, aber auch nur diese, nicht auf gesamter Breite des JTextPane
- Wechsel ich mit Return in die nächste Zeile, ist das Highlighting aus Zeile 1 wieder weg (was so richtig ist) und tippe ich nun in Zeile 2 Zeichen, werden wieder die eingegebenen Zeichen farblich hinterlegt, nur nicht die gesamte Zeile.
- Wechsel ich nun mit dem Caret zurück in Zeile 1, egal ob mit Mausklick oder Cursor up, so wird die Zeile 1 in der gesamten Breite farblich hinterlegt, so wie es von Anfang an sein sollte.

Ich hoffe, mir kann hier jemand sagen, was ich falsch mache, bzw. erklären, wieso es nicht funkionieren kann.
Gern nehme ich auch alternative Lösungsansätze entgegen, wie man die Anforderung noch ganz anders realisieren kann.

Vielen Dank schonmal im Vorfeld für Eure Idee.
Gruß
Preachie

[code=Java]import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;

import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;

public class HighlightProblem extends JFrame {
	private static final long serialVersionUID = 1L;
	private final JTextPane textPane;
	private final Highlighter.HighlightPainter cyanPainter;
	
	public HighlightProblem() {
		cyanPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.CYAN);

		textPane = new JTextPane();
		textPane.setPreferredSize(new Dimension(500, 300));
		textPane.setHighlighter(new LineHighlighter());
		textPane.addCaretListener(new CaretListener() {
			@Override
			public void caretUpdate(CaretEvent e) {
				setHighlight(e);
			}
		});
		getContentPane().add(textPane);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		pack();
		setVisible(true);
	}

	public static void main(String[] args) {
		new HighlightProblem();
	}

	public void setHighlight(CaretEvent e) {
		textPane.getHighlighter().removeAllHighlights();
		int currentLine = getLineFromOffset(textPane, e.getDot());
		int startPos = getLineStartOffsetForLine(textPane, currentLine);
		int endOffset = getLineEndOffsetForLine(textPane, currentLine);
		
		try {
			textPane.getHighlighter().addHighlight(startPos, endOffset, cyanPainter);			
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		textPane.repaint();
	}

	public int getLineFromOffset(JTextComponent component, int offset) {
		return component.getDocument().getDefaultRootElement().getElementIndex(offset);
	}

	public int getLineStartOffsetForLine(JTextComponent component, int line) {
		return component.getDocument().getDefaultRootElement().getElement(line).getStartOffset();
	}

	public int getLineEndOffsetForLine(JTextComponent component, int line) {
		return component.getDocument().getDefaultRootElement().getElement(line).getEndOffset();
	}

	public class LineHighlighter extends DefaultHighlighter {
		private JTextComponent component;

		@Override
		public final void install(final JTextComponent c) {
			super.install(c);
			this.component = c;
		}

		@Override
		public final void deinstall(final JTextComponent c) {
			super.deinstall(c);
			this.component = null;
		}

		@Override
		public final void paint(final Graphics g) {
			final Highlighter.Highlight[] highlights = getHighlights();
			final int len = highlights.length;
			for (int i = 0; i < len; i++) {
				Highlighter.Highlight info = highlights[i];
				if (info.getClass().getName().indexOf("LayeredHighlightInfo") > -1) {
					// Avoid allocing unless we need it.
					final Rectangle a = this.component.getBounds();
					final Insets insets = this.component.getInsets();
					a.x = insets.left;
					a.y = insets.top;
					// a.width -= insets.left + insets.right + 100;
					a.height -= insets.top + insets.bottom;
					final Highlighter.HighlightPainter p = info.getPainter();
					p.paint(g, info.getStartOffset(), info.getEndOffset(), a, this.component);
				}
			}
		}
		
		@Override
		public void removeAllHighlights() {
			textPane.repaint(0, 0, textPane.getWidth(), textPane.getHeight());
			super.removeAllHighlights();
		}
	}
}
 

KrokoDiehl

Top Contributor
Hallo.
Ich habe -so denke ich- das was du suchst aus einer Kombination von Santhosh Kumar's Weblog
und
How can I highlight the current row in a JTextArea?
hinbekommen (du wirst den Code sicher wiedererkennen ;) ):
Java:
public final class RowHighlighter implements Highlighter.HighlightPainter
{ 
    private final Color color; 

    public RowHighlighter() { 
        this(new Color(225, 236, 247)); 
    } 

    public RowHighlighter(Color color) { 
        this.color = color; 
    } 
 
    @Override
    public void paint(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c) { 
        Rectangle alloc = bounds.getBounds(); 
        try { 
            TextUI mapper = c.getUI(); 
            Rectangle p0 = mapper.modelToView(c, offs0); 
            Rectangle p1 = mapper.modelToView(c, offs1); 
 
            g.setColor(color); 
            if(p0.y==p1.y) { 
                Rectangle r = p0.union(p1); 
                g.fillRect(r.x, r.y, r.width, r.height); 
            }
            else { 
                int p0ToMarginWidth = alloc.x+alloc.width-p0.x; 
                g.fillRect(p0.x, p0.y, p0ToMarginWidth, p0.height); 
                if ((p0.y+p0.height)!=p1.y) { 
                    g.fillRect(alloc.x, p0.y+p0.height, alloc.width, 
                            p1.y-(p0.y+p0.height)); 
                } 
                g.fillRect(alloc.x, p1.y, (p1.x-alloc.x), p1.height); 
            } 
        }
        catch(BadLocationException e) { 
        } 
    } 

} //class RowHighlighter
Hier habe ich "nur" die Wrappermethode
Code:
_paint()
direkt in
Code:
paint()
gemacht, ohne dass er mit den Offsets was macht. Das führte bei mir nur zum falschen Zeichnen.

Danach habe ich den CaretListener aus dem 2. Link entsprechend übernommen:
Java:
    private final class HighlightChanger implements CaretListener {

        private Object highlighterID = null;
        private final Highlighter.HighlightPainter painter;
        
        public HighlightChanger() {
            super();
            painter = new RowHighlighter();
        }
        
        @Override
        public void caretUpdate( CaretEvent event ) {
            final JTextComponent comp = (JTextComponent) event.getSource();
            if (comp != null && highlighterID != null) {
                comp.getHighlighter().removeHighlight(highlighterID);
                highlighterID = null;
            }
                
            int     pos     = comp.getCaretPosition();
            Element element = Utilities.getParagraphElement(comp, pos);
            int     start   = element.getStartOffset();
            int     end     = element.getEndOffset();
            
            try {
                highlighterID = comp.getHighlighter().addHighlight(
                        start, end, painter);
            }
            catch (BadLocationException exc) {
            }
        }
    } //class HighlightChanger
 

preachie

Aktives Mitglied
Vielen Dank Leute,

nachdem ich mir zunächst die vorgeschlagene Lösung vom Kroko angesehen habe, finde ich die LinePainter Klasse noch deutlich eleganter. Damit klappt es nun wie gewünscht :)
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
B JavaFX Bei Scenen-Wechsel im primaryStage wird aktuelle Fenstergröße nicht mit übernommen AWT, Swing, JavaFX & SWT 16
P JavaFX aktuelle Tabellenzeile bei Choice-Box-Auswahl in Zelle ermitteln AWT, Swing, JavaFX & SWT 28
E Aktuelle Uhrzeit auf jeder Stage anzeigen lassen (JavaFX) AWT, Swing, JavaFX & SWT 2
F JavaFX Aktuelle Zeit in einem TextField anzeigen AWT, Swing, JavaFX & SWT 7
M Java FX Immer aktuelle Mausposition anzeigen AWT, Swing, JavaFX & SWT 6
K Swing Aktuelle Uhrzeit anzeigen AWT, Swing, JavaFX & SWT 3
T Swing Aktuelle Größe eines Textes in einem Label darstellen AWT, Swing, JavaFX & SWT 3
D JFreeChart - aktuelle code beispiele AWT, Swing, JavaFX & SWT 11
B aktuelle Position des Fensters ermitteln AWT, Swing, JavaFX & SWT 3
M Aktuelle Mausposition im Koordinatensystem AWT, Swing, JavaFX & SWT 3
G Aktuelle Mausposition auslesen und ausgeben AWT, Swing, JavaFX & SWT 2
G aktuelle panel herausfinden AWT, Swing, JavaFX & SWT 7
S aktuelle möglichkeit images zu laden? AWT, Swing, JavaFX & SWT 2
S [AWT] Aktuelle Version, bzw. Referenz? AWT, Swing, JavaFX & SWT 3
M JavaFX TableView nur erste Zeile editable machen und gelb markieren AWT, Swing, JavaFX & SWT 0
F Zeile in mehreren Jtables bei Selektion markieren AWT, Swing, JavaFX & SWT 11
missy72 JavaFX TableRow / RowFactory Zeile einfärben AWT, Swing, JavaFX & SWT 9
T Zelle- und die Zeile-Farbenwechsel bei der Selektion in der Tabelle AWT, Swing, JavaFX & SWT 4
M TableView Zeile hinzufügen AWT, Swing, JavaFX & SWT 5
I JLabel neue Zeile AWT, Swing, JavaFX & SWT 4
B JavaFX TableView eine Zeile markieren AWT, Swing, JavaFX & SWT 5
C SWT Breadcrumb Zeile mit entsprechenden Hyperlinks erstellen AWT, Swing, JavaFX & SWT 0
VfL_Freak Swing Einzelne Zeile in jTable selektieren klappt nicht AWT, Swing, JavaFX & SWT 7
Bluedaishi JTextArea gefundene Zeile nach Oben Scrollen AWT, Swing, JavaFX & SWT 13
B Zeile einer Tabelle selektieren AWT, Swing, JavaFX & SWT 1
T Swing Tabelle mit Button - Anzeigefehler nach Zeile entfernen AWT, Swing, JavaFX & SWT 1
T Swing JTable Zeile mit ausgelesenen Werten mit Hilfe von einem Button hinzufügen AWT, Swing, JavaFX & SWT 1
D JLabel bei Aufruf neue Zeile AWT, Swing, JavaFX & SWT 5
C Button Text in JList neue Zeile AWT, Swing, JavaFX & SWT 6
J Swing JTable Zeile nicht auswählbar machen AWT, Swing, JavaFX & SWT 0
F Swing String[] in JTextArea ausgeben. Jeder Eintrag in neue Zeile, aber ohne "\n"- Geht das? AWT, Swing, JavaFX & SWT 3
N AWT Markierte Zeile jList aus mySQL DB löschen AWT, Swing, JavaFX & SWT 2
J JTable Zeile anklicken und neues Frame öffnen AWT, Swing, JavaFX & SWT 4
S JTable nach aktualisierung - neue Zeile nicht "klickbar" AWT, Swing, JavaFX & SWT 0
D Swing Letzte Zeile einer JTable nicht über RowSorter sotieren AWT, Swing, JavaFX & SWT 2
M Text Area 1. Zeile oben AWT, Swing, JavaFX & SWT 4
I ausgewählte Zeile mit Hilfe der Tastatur löschen! AWT, Swing, JavaFX & SWT 3
B jTable ganze Zeile anhand eines Kriterium färben AWT, Swing, JavaFX & SWT 6
T JtextPane Zeile aktualisieren AWT, Swing, JavaFX & SWT 3
M JTextArea Zeile hinzufügen AWT, Swing, JavaFX & SWT 4
M Swing JScrollPane (Parent JTextArea) aktualisieren + neue Zeile AWT, Swing, JavaFX & SWT 5
P Swing Alle Zeilen einer Spalte (jTable) zusammen zählen und in eine eigene Zeile das Ergebnis schreiben. AWT, Swing, JavaFX & SWT 7
Ollek Swing JTable - Zeile löschen mit AbstractTableModel AWT, Swing, JavaFX & SWT 20
S Swing Kopieren einer vollständigen Zeile einer JTable AWT, Swing, JavaFX & SWT 3
F GroupableTableHeader zeigt nur eine Zeile AWT, Swing, JavaFX & SWT 4
H Unterschiedliche JComboBox je JTable Zeile AWT, Swing, JavaFX & SWT 4
N Swing FileReader Zeile lesen AWT, Swing, JavaFX & SWT 5
C SWT Wie greife ich auf den Inhalt einer bestimmten Zeile zu? (TableViewer) AWT, Swing, JavaFX & SWT 7
F SWT Tabelle Zeile auslesen AWT, Swing, JavaFX & SWT 3
J Swing JTable: Komplette Zeile aber ohne Spalten markieren AWT, Swing, JavaFX & SWT 11
K Zeile verbinden AWT, Swing, JavaFX & SWT 2
G Zeile in JTable durch rechte Maustaste manipulieren AWT, Swing, JavaFX & SWT 4
S Swing AWT-Exception bei JTable mit JComboBox beim Löschen der letzten Zeile AWT, Swing, JavaFX & SWT 3
S Tabelle sortieren, mit Ausnahme der letzten Zeile AWT, Swing, JavaFX & SWT 9
H Swing JComboBox in einer Zeile AWT, Swing, JavaFX & SWT 3
Meldanor Swing JTable - Eine neue Zeile vor einer bestehenden Einfügen AWT, Swing, JavaFX & SWT 2
F Zusätzliche Zeile in der GUI AWT, Swing, JavaFX & SWT 4
H Zeile in DefaultTableModel hinzufügen, ProgressBar AWT, Swing, JavaFX & SWT 4
H Markierte Zeile löschen AbstractTableModel AWT, Swing, JavaFX & SWT 10
R Zeile in JTable anhand von Wert einfärben AWT, Swing, JavaFX & SWT 2
M Jframe wie bekommt man bei den zeile einen header erzeugen AWT, Swing, JavaFX & SWT 2
N JTable, Zeile bleibt immer selektiert.... AWT, Swing, JavaFX & SWT 3
Dit_ JTextArea zu Zeile X scrollen AWT, Swing, JavaFX & SWT 4
M [erledigt] Bestimmte Zeile aus JTextArea löschen AWT, Swing, JavaFX & SWT 3
F Swing JTable: Problem beim zeile löschen AWT, Swing, JavaFX & SWT 3
J Swing JList... mehrere Strings in Zeile AWT, Swing, JavaFX & SWT 8
N Methode zum ermitteln der editierte Zeile/Zelle in jTable AWT, Swing, JavaFX & SWT 8
C Mit SelectionListener herausfinden welche zeile in Jtable angeklickt wurde AWT, Swing, JavaFX & SWT 5
E In JTable neue Zeile mit Tabulator einfügen AWT, Swing, JavaFX & SWT 5
M Text in txt-Datei in letzte Zeile schreiben? AWT, Swing, JavaFX & SWT 14
R JTable Hintergrund der Zeile abhängig von Inhalt einer Zelle verändern AWT, Swing, JavaFX & SWT 3
Developer_X Swing text von bestimmter zeile in jtextarea herausbekommen. AWT, Swing, JavaFX & SWT 12
R JTable Zeile löschen AWT, Swing, JavaFX & SWT 4
T MyTableCellRenderer selektiert nicht die ganze Zeile AWT, Swing, JavaFX & SWT 3
R FlowLayout: 1 Objekt pro Zeile AWT, Swing, JavaFX & SWT 5
D eigenes Tablemodel, Zeile löschen ArrayindexOOB excp AWT, Swing, JavaFX & SWT 4
C JTable mit RowSorter und Drag & Drop: Zeile verschieben AWT, Swing, JavaFX & SWT 4
P JTable zeile einfärben AWT, Swing, JavaFX & SWT 1
N Farbe einer einzelnen Zeile einer JTable ändern AWT, Swing, JavaFX & SWT 10
G Componente Zeile fixieren AWT, Swing, JavaFX & SWT 3
dl85hej bestimmte Zeile anspringen AWT, Swing, JavaFX & SWT 3
S Zeile an eine Tabelle anfügen AWT, Swing, JavaFX & SWT 5
R JTable: Zellen einer Zeile zusammenfassen? AWT, Swing, JavaFX & SWT 3
D JTable um eine Zeile erweitern AWT, Swing, JavaFX & SWT 4
P Tabellen in Java - Zeile anhängen AWT, Swing, JavaFX & SWT 19
GilbertGrape JTable - immer leere Zeile AWT, Swing, JavaFX & SWT 6
A JTable zeile auswählen AWT, Swing, JavaFX & SWT 2
A JXTable jede zweite Zeile einfärben AWT, Swing, JavaFX & SWT 4
S in JTable eine Zeile färben AWT, Swing, JavaFX & SWT 5
T JTable ohne Titel in der ersten Zeile AWT, Swing, JavaFX & SWT 2
K leere Zeile zu JTable zufügen AWT, Swing, JavaFX & SWT 2
T jtabel - Zeile selktierbar aber nicht editierbar AWT, Swing, JavaFX & SWT 2
E JTable letzte Zeile in Fett schrift? AWT, Swing, JavaFX & SWT 3
O JTable + event wenn andere Zeile selektiert ist AWT, Swing, JavaFX & SWT 5
J jTextarea Anzahl Zeichen in einer Zeile begrenzen AWT, Swing, JavaFX & SWT 2
O JTable Zeile zuweisen und weiter mit dem Button AWT, Swing, JavaFX & SWT 2
M JTable & Problem, das nicht die komplette Zeile gefärbt AWT, Swing, JavaFX & SWT 6
G JTable erste zeile fixieren wie in excel? AWT, Swing, JavaFX & SWT 3
Z JTable automatisch zu einer Zeile scrollen AWT, Swing, JavaFX & SWT 4
lolkind eine Zeile und Tabelle ist Rechtsbündig? AWT, Swing, JavaFX & SWT 3

Ähnliche Java Themen

Neue Themen


Oben