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
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();
}
}
}