Zeichen verschiedenfarbig in einer JTextPane darstellen

Status
Nicht offen für weitere Antworten.

Youlian

Mitglied
Hallo,

ich bin langzeitiger Leser und nun zum ersten mal Poster hier, da ich nun bei meinem Problem schon längere Zeit anstehe.

Nun zu meinem Projekt: Ich habe einen Art Editor programmiert der auch syntax-Highlighting unterstützen soll.
Die Schlüsselwörter werden vorher aus einer XML Datei eingelesen: Es gibt Kommandos, Funktionen, spezielle Variablen, Kommentare und noch ein paar andere... Das ist aber für mein eigentliches Problem nicht so wichtig.

Also:

Ich habe eine JTextPane der ich ein javax.swing.text.DefaultStyledDocument (ab jetzt: doc) zuweise.

Dieses doc erzeuge ich mir mit dem Konstruktor der einen StyleContext nimmt. In diesem StyleContext sind meine Styles die später zuweisen werde abgelegt. Die Stylehierarchie ist nichts Besonders. -> Alle Styles haben als "parent"-Style den DefaultStyle und unerscheiden sich nur im Attribut "Foreground" (also in meinem Fall, Textfarbe) von einander.

Nun gibt es in meinem Editor noch ein scanner-Objekt, dass bestimmt welche Farbe/Style welche Zeichen haben sollen.
Diese Scanner-Klasse ist erneut nichts großartiges, und macht auch keinen großen Rechenaufwand.
Diesem scanner-objekt gebe ich noch mein DefaultStyleDocument bekannt (es bekommt eine Referenz).

Auf dem Document habe ich einen DocumentListener regestriert der nichts anderes macht als bei insertUpdate (es gibt noch changeUpdate und removeUpdate) die Methode scan() auf dem scannerObjekt aufzurufen.

Die scan Methode schnappt sich mit doc.getText() den Inhalt (string) des docs (also gleichzeitig den Inhalt der JTextPane) und parst diesen. Jedes mal wenn ein vollständiger Token erkannt wurde setze ich mit
Code:
this.doc.setCharacterAttributes(drawFrom, pos, this.doc.getStyle(""+this.token), true);
für diesen Abschnitt/Token den Style mit der richtigen Farbe. drawFrom ist hierbei der Anfang des tokens, pos die Länge; mit this.doc.getStyle(String) hole ich mir den entsprechenden Style aus dem DefaultStyleDocument, dem ich im Konstruktor meinen vorbereiteten StyleContext übergeben habe, true -> heißt das ich die bisherigen Attribute für diesen Abschnitt überschreiben will) ""+this.token, desshalb weil mein token nur ein int ist, dieser int legt fest um welche Art von Schlüsselwort es sich handelt. Die Stylenamen sind einfach Nummern: "1", "2".. etc..

Ok - so weit so gut. Es funktioniert grundsätzlich - nur elend langsam.

Falls ich das scan() direkt im AWT-Thread der das insertUpdate des DocumentListeners kommt wie zu erwarten, (oder wenn man gleich mit copy & paste ganze textblöcke einfügt) eine "Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Attempt to mutate in notification". Die setCharacterAttributes() ist nämlich "thread-sicher" im Gegensatz zu den meisten anderen Swing-Methoden.

Also habe ich das scannen und setzen der Styles in einen eigenen Thread ausgelagert. (Bei jedem insertupdate wird ein neuer Thread angelegt).
Jetzt flackert der Text bei jedem Tastendruck wie wild herum, da die Styles immer neu gesetzt werden. Außerdem geht die Prozessorauslastung beim Einfügen größere Textblöcke sehr schnell auf 100%. (10 Zeilen kopieren und dann schnell 10 mal STRG+V und man kann mit eigenen Augen zusehen wie er die Styles setzt :/, diesen Test nenne ich ab jetzt "schnelles Einfügen")
Um das "Flackern" (in der JTextPane) wegzubekommen habe ich versucht DoubleBuffered auf true zu setzen -> kein erfolg.

Nun habe ich das Scannen und Setzen mit SwingUtilities.invokeLater(new Runnable() { ... }); probiert, also wieder vom AWT-Thread machen zu lassen.
Das Flackern war weg, aber dafür war es noch unperformanter. Und wenn man jetzt das "schnelle Einfügen" gemacht hat dann war die ganze GUI für 2-3 Sekunden nicht ansprechbar weil der AWT Thread beschäftigt war.

Ein weiter Ansatz der nicht wirklich was gebracht hat war einen Thread der beim Erzeugen der Scannerklasse ebenfalls erstellt wurde und dann mit Hilfe eines Objects und eines boolean so synchronisiert wurde, dass er immer schläft außer es tritt ein insertUpdate am Dokument auf: läuft in einer Endlosschleif als Daemon und wird immer dann vom AWT-Thread aufgeweckt wenn das Dokument verändert wurde, der awt-Thread setzt also das parse-boolean auf true weckt den Scanner-Thread auf und ist fertig mit insertUpdate. Der ScannerThread scannt und setzt die Styles setzt den parse boolean auf false und legt sich wieder schlafen. -> Kein Performancegewinn, Flacker vermindert aber nicht weg; außerdem wurde oft das letze Schlüsselwort beim copy & paste nicht richtig gehighlightet da manche insertUpdate( wo ich den parse boolean auf true setze und den thread aufwecke (notifyAll();) einfach verpufft sind, da der Thread noch nicht wieder mit dem Scannen fertig war, aber schon ein neues insertUpdate-Event ausgelöst wurde

Ein ganz ein anderer Ansatz -> der vorher schon einma perfekt funktioniert hat:
Das Dokument wird immer dann neu geparst wenn der Text in der JTextPane neu gezeichnet werden muss.
Es wurde die API-Methode drawUnselectedText(Graphics g) überschrieben und vor jedem "Zeichnen" (am Bildschirm) die aktuelle Zeichenfarbe auf die gewünschte Farbe gesetzt. So wurde dann Token für Token auf den Bildschirm gezeichnet. Das war flacker und ruckelfrei möglich. Daher bin ich mir auch ziemlich sicher, dass die Scan-Funktion nicht die Bremse/der große Aufwand ist, da die drawUnselectedText nicht nur aufgerufen wurde wenn sich der Inhalt des Dokuments verändert hat sondern immer dann wenn der Text neu gezeichnet werden muss. (also zB. auch dann wenn das Fenster verschoben wird oder man mit dem Mauszeiger darüberfährt)
Ich hab den Ansatz dann verworfen, weil ich den Editor noch erweitern will (Autovervollständigung) und es sehr schwer ist, dann hinter die gezeichneten Tokens noch Logik zu legen. Generell ist es kein schönes Konzept. (nicht Java :p)

Sachen die ich bereits probiert habe, keinen Unterschied/Erfolg gebracht haben:
die JTextPane.setDoubleBuffered(true); setzen
eigener Thread für jeden Parsevorgang
SwingUtilites.invokeLater()
Einzelner Thread der parst und sich dann wieder schlafen legt.
(Zeichenfarbe vor jedem Token setzen *pfui* schmutzig)

Sachen die ich noch nicht ausprobiert habe, weil ich nicht glaube, dass sie was bringen:
einen eigenen Thread (entweder einzelner mit Schlafen legen oder immer neuen pro Parsen) fürs Parsen der statt dass er die Styles setzt die Position(start, ende) und Schlüsselwort eine Collection anlegt und dann mit SwingUtilities.invokeLater() dem AWT Thread sagt, dass dieser diese Styles setzten soll -> (ich glaube nicht, dass das Scannen die Bremse ist, siehe oben, ich glaube der Flaschenhals ist das setzen der Styles)

Mach ich vom Konzept her etwas falsch? - Ich weiß echt nicht mehr weiter. Hab extra schon wie inder API beschrieben ein Document mit StyleContext, damit für alle Textabschnitte mit gleicher Farbe auch das gleiche Style-Objekt verwendet wird, erstellt.
Falls sich wirklich jemand die Mühe machne würde und sich den Code anschauen will, ich kann ihn soweit es geht vom bestehenden Code trennen (so viel, wie es sich vielleicht anhört ist es auch wieder nicht) (Scanner-Klasse liefert dann halt nur Random-dummy Farben). -> Ich wäre demjenigen dann ewig dankbar. Anbieten kann ich euch für eure Hilfe leider nichts. (Ist bloß ein freiwillges Projekt eines Klassenkameradens und mir für die Schule),

Ein weiterer Versuch wäre ein Thread der das Dokument einfach in gewissen Zeitabstand scannt. Ich glaub, da tritt das Problem des flackerns aber wieder auf :(

Falls irgendetwas noch unklar: Einfach hier posten.

Ich bin für jede Hilfe dankbar -> weiß inzwischen echt nicht mehr weiter.
Youlian
 

Wildcard

Top Contributor
hmm.... jede Menge Informationen....
Bevor man da irgendetwas angeht solltest du das echte Performanceproblem herausarbeiten.
Lass dazu einen Profiler über die Anwendung laufen, dann sollte der Bösewicht schnell gefunden sein.
Sobald du mehr weißt: Melde dich nochmal.
 

Youlian

Mitglied
Wildcard hat gesagt.:
Lass dazu einen Profiler über die Anwendung laufen, dann sollte der Bösewicht schnell gefunden sein.

Hallo,
ich kann zwar erahnen was so ein Profiler macht, habe aber noch nie einen benutzt, bzw. kenne kein geeignetes Programm.
Kannst du mir einen empfehlen. (Link?)
Und danke für die schnelle Antwort. :)
 

Illuvatar

Top Contributor
Wenn du Eclipse verwendest, schau einfach mal bei den Plugins davon.

Oder du verwendest den Profiler, den Java eingebaut hat. Er lässt sich über den Kommandozeilenparameter -Xrunhprof starten. Mehr dazu steht zum Beispiel im Javabuch (ich glaub das ist Kapitel 49, das Kapitel zu Performance eben).
 

Youlian

Mitglied
Da ich NetBeans verwende habe ich mir dafür den Profiler 5.5 runtergeladen, das Tutorial gemacht und hier sind die Ergebnisse (nochmals Danke für den Tipp, ich habe vorher nicht gewusst, dass es so einfach zu bedienende aber dennoch brauchbare Tools gibt; war eher der Meinung, dass das was für Experten die in der Console und auf einer tieferenen Ebene rumhantieren, ist):



Wie ich befürchtet habe ist der Auslöser die thread-sichere swing-Funktion "setCharacterAttributes". Diese fordert eine Schreibsperre an-> (soweit ich das aus der API richtig verstanden habe). Also mache ich das natürlich mit einem synchronisierten Thread, statt für jeden Parsevorgang einen eigenen Anzulegen. Weiters ist es mir gelungen, nicht mehr das ganze Dokument zu parsen, sondern nur mehr den Teil (besser gesagt: die Zeile in der sich etwas verändert hat). Ich war ziemlich happy, musste aber mit Ernüchterung feststellen, dass das nur wenig bis sehr wenig gebracht hat.
Die oben erwähnte Methode braucht bei mehreren threads ca. 95% der Laufzeit (sagt man das so?) und bei einem Thread immerhin noch 90%.

Zur Zeit mache ich es so:
Ein Thread parst und setzt Attribute und wird vom awt-thread aufgeweckt.

Zu meiner Verwunderung ging es am Besten wenn ich alles vom awt-Thread machen hab lassen!
Dann ist mir auch eingefallen warum das so sein könnte: Ein Thread verändert die Zuweisung eines Styles im Dokument -> es wird ein AttributeChanged (oder so ähnlich, habs bis jetzt noch nicht gefunden)-Event geworfen und der awt-Thread wird von diesem angestoßen das die TextPane neu zu zeichnen -> Wenn alles der awt-Thread macht (SwingUtilities.invokeLater()) dann wird die JTextPane nur einmal neu gezeichnet, und zwar wenn der Thread mit parsen fertig ist. -- So oder so ähnlich stelle ich mir das zumindest vor. - Ich kann mich natürlich auch irren.

Nun wäre es toll wenn man am Dokument irgendwo einstellen kann, dass dieses AttributeChangeEvent (ich weiß nicht wie es wirklich heißt) nicht geworfen wird. -> Ich habe schon die API durchsucht und auch geglaubt, dass ich es gefunden habe. Hat jedoch nicht funktioniert oder war eine Methode die für etwas anderes gedacht war. Weiß einer von euch darüber bescheid oder kann mir anderwertig weiterhelfen?

Youlian
 

Wildcard

Top Contributor
Mein Vorschlag: Setz ein eigenes StyledDocument das erst dann ein Event feuert wenn du fertig mit dem Parsen bist und alle Attributes gesetzt sind.
 

Youlian

Mitglied
In der API habe ich im AbstractDocument (von dem das DefaultStyledDocument erbt) diese 3 Methoden gefunden:

Code:
protected  void fireChangedUpdate(DocumentEvent e)

protected  void fireInsertUpdate(DocumentEvent e)

protected  void fireRemoveUpdate(DocumentEvent e)
Notifies all listeners that have registered interest for notification on this event type.

Wie genau gehe ich jetzt beim Überschreiben der Methoden vor ? Sind das überhaupt dir richtigen?
Weiters habe ich noch folgendes gefunden

Code:
protected  void writeLock()
Acquires a lock to begin mutating the document this lock protects.
Code:
protected  void writeUnlock()
Releases a write lock previously obtained via writeLock.

Muss oder soll ich Locks setzen wenn ich die Attribute für den Inhalt neu zuweise?
 

Wildcard

Top Contributor
Überschreib doch setCharacterAttributes. Mit Copy/Paste kannst du die alte Implementierung übernehmen, feuerst das Event aber nicht. Am ende triggerst du dann manuell.
 

Youlian

Mitglied
Code:
    /**
     * Sets attributes for some part of the document.
     * A write lock is held by this operation while changes
     * are being made, and a DocumentEvent is sent to the listeners 
     * after the change has been successfully completed.
     * 


     * This method is thread safe, although most Swing methods
     * are not. Please see 
     * <A HREF="http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html">How
     * to Use Threads</A> for more information.     
     *
     * @param offset the offset in the document >= 0
     * @param length the length >= 0
     * @param s the attributes
     * @param replace true if the previous attributes should be replaced
     *  before setting the new attributes
     */
    public void setCharacterAttributes(int offset, int length, AttributeSet s, boolean replace) {
        if (length == 0) {
            return;
        }
	try {
	    writeLock();
	    DefaultDocumentEvent changes = 
		new DefaultDocumentEvent(offset, length, DocumentEvent.EventType.CHANGE);

	    // split elements that need it
	    buffer.change(offset, length, changes);

	    AttributeSet sCopy = s.copyAttributes();

	    // PENDING(prinz) - this isn't a very efficient way to iterate
	    int lastEnd = Integer.MAX_VALUE;
	    for (int pos = offset; pos < (offset + length); pos = lastEnd) {
		Element run = getCharacterElement(pos);
		lastEnd = run.getEndOffset();
                if (pos == lastEnd) {
                    // offset + length beyond length of document, bail.
                    break;
                }
		MutableAttributeSet attr = (MutableAttributeSet) run.getAttributes();
		changes.addEdit(new AttributeUndoableEdit(run, sCopy, replace));
		if (replace) {
		    attr.removeAttributes(attr);
		}
		attr.addAttributes(s);
	    }
	    changes.end();
	    fireChangedUpdate(changes);
	    fireUndoableEditUpdate(new UndoableEditEvent(this, changes));
	} finally {
	    writeUnlock();
	}

    }

Du meinst ich soll da sozusagen einfach die fire***-Methoden auskommentieren und dann wenn ich mit dem setzen der Attribute fertig bin auf der JTextPane ein validate() machen?
 

Wildcard

Top Contributor
Ich hab mich mit StyledDocuments ehrlich gesagt nie beschäftigt, daher bin ich nicht sicher was im Hintergrund alles passiert. Wenn ich mir den Source so ansehe, würde ich diese 3 Zeilen:
Code:
       changes.end();
       fireChangedUpdate(changes);
       fireUndoableEditUpdate(new UndoableEditEvent(this, changes));
entfernen, und gegebenenfalls den lock. Dann machst du in deiner abgeleiteten Klasse eine flush Methode in der dieser Code ausgeführt wird. Diese Methode rufst du auf sobald du mit dem Scanner durch bist.
Dann mal schauen was sich in der Performance verändert.
Als nächstes würde ich mir dann überlegen ob dein Document den Scanner nicht selbst verwenden sollte, anstatt von aussen Attribute gesetzt zu bekommen.
 

Youlian

Mitglied
Ok, schonmal Danke für die Hilfe.
Das werde gleich morgen ausprobieren (heute nicht mehr, hab erstmal genug von Java :wink: ).

Ich wünsche noch einen schönen Sonntag Abend.
 

Youlian

Mitglied
Also ich habe jetzt meine eigenes DefaultStyledDocument und die ensprechenden Methoden sehen wie folgt aus:
(wenn ich versuche ohne Lock; writeLock() das Attribut zu sethen dann schmeißt er bei
buffer.change(offset, length, changes); eine
"Exception in thread "uc4-script-parser" javax.swing.text.StateInvariantError: Illegal cast to MutableAttributeSet" - Exception.

Also lass ich das Lock drinnen und kommentier einfach mal die beiden Methoden die die Events werfen auf die der awt anspringt aus:


Code:
public void setCharacterAttributes(int offset, int length, AttributeSet s, boolean replace) {
        if (length == 0) {
            return;
        }
        try {
            writeLock();
            DefaultDocumentEvent changes =
                    new DefaultDocumentEvent(offset, length, DocumentEvent.EventType.CHANGE);
            
            // split elements that need it
            buffer.change(offset, length, changes);
            
            AttributeSet sCopy = s.copyAttributes();
            
            // PENDING(prinz) - this isn't a very efficient way to iterate
            int lastEnd = Integer.MAX_VALUE;
            for (int pos = offset; pos < (offset + length); pos = lastEnd) {
                Element run = getCharacterElement(pos);
                lastEnd = run.getEndOffset();
                if (pos == lastEnd) {
                    // offset + length beyond length of document, bail.
                    break;
                }
                MutableAttributeSet attr = (MutableAttributeSet) run.getAttributes();
                changes.addEdit(new AttributeUndoableEdit(run, sCopy, replace));
                if (replace) {
                    attr.removeAttributes(attr);
                }
                attr.addAttributes(s);
            }
            changes.end();
            //fireChangedUpdate(changes);
            //fireUndoableEditUpdate(new UndoableEditEvent(this, changes));
        } finally {
            writeUnlock();
        }
    }
    
//der Offset, Length in dieser Methode "überspannt" alle Attribute die in der obigen Methode gesetzt wurden
//zb. wurde oben an der Position 3 mit länge 4 und an der position 7 mit länge 2 die Attribute gesetzt
// dann ist dieser offset 3 und die länge 6
    public void flush(int offset, int length) {
        if (length == 0) {
            return;
        }
            DefaultDocumentEvent changes = new DefaultDocumentEvent(offset, length, DocumentEvent.EventType.CHANGE);
            changes.end();
            fireChangedUpdate(changes);
            fireUndoableEditUpdate(new UndoableEditEvent(this, changes));
    }

Mit dem Ergebnis das die Methode jetzt nur mehr 5% der ganzen Programmlaufzeit in Anspruch nimmt !!! (getestet anhand eines sehr langen Codestücks)
Der geparste Text bleibt - wie zu erwarte, da der AWT-Thread nicht anspringt und neu zeichnet - weiß.
Jedoch tritt bei der 2 Veränderung (als noch nicht beim 1. Einfügen, oder nach einmaligen drücken einer Taste: zb: Schreiben eines beliebigen Buchstabens, oder Einfügen vieler Zeilen Scriptcodes) sondern genau bei der 2. Veränderung eine Exception. (egal ob ich meine flush Methode aufrufe oder nicht.)

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.text.CompositeView.replace(CompositeView.java:170)
at javax.swing.text.View.updateChildren(View.java:1095)
at javax.swing.text.View.insertUpdate(View.java:679)
at javax.swing.text.FlowView.insertUpdate(FlowView.java:238)
at javax.swing.text.View.forwardUpdateToView(View.java:1186)
at javax.swing.text.View.forwardUpdate(View.java:1161)
at javax.swing.text.BoxView.forwardUpdate(BoxView.java:223)
at javax.swing.text.View.insertUpdate(View.java:685)
at javax.swing.plaf.basic.BasicTextUI$RootView.insertUpdate(BasicTextUI.java:1589)
at javax.swing.plaf.basic.BasicTextUI$UpdateHandler.insertUpdate(BasicTextUI.java:1848)
at javax.swing.text.AbstractDocument.fireInsertUpdate(AbstractDocument.java:185)
at javax.swing.text.AbstractDocument.handleInsertString(AbstractDocument.java:734)
at javax.swing.text.AbstractDocument.insertString(AbstractDocument.java:693)
at javax.swing.text.AbstractDocument.replace(AbstractDocument.java:655)
at javax.swing.JTextPane.replaceSelection(JTextPane.java:178)
at javax.swing.JTextPane.replaceSelection(JTextPane.java:162)
at javax.swing.plaf.basic.BasicTextUI$TextTransferHandler.handleReaderImport(BasicTextUI.java:2341)
at javax.swing.plaf.basic.BasicTextUI$TextTransferHandler.importData(BasicTextUI.java:2482)
at javax.swing.TransferHandler.importData(TransferHandler.java:745)
at javax.swing.plaf.basic.BasicTextUI$TextTransferHandler.importData(BasicTextUI.java:2419)
at javax.swing.TransferHandler$TransferAction.actionPerformed(TransferHandler.java:1655)
at javax.swing.text.JTextComponent.invokeAction(JTextComponent.java:1485)
at javax.swing.text.JTextComponent.paste(JTextComponent.java:1463)
at javax.swing.text.DefaultEditorKit$PasteAction.actionPerformed(DefaultEditorKit.java:1337)
at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1636)
at javax.swing.JComponent.processKeyBinding(JComponent.java:2844)
at javax.swing.JComponent.processKeyBindings(JComponent.java:2879)
at javax.swing.JComponent.processKeyEvent(JComponent.java:2807)
at java.awt.Component.processEvent(Component.java:5815)
at java.awt.Container.processEvent(Container.java:2058)
at java.awt.Component.dispatchEventImpl(Component.java:4410)
at java.awt.Container.dispatchEventImpl(Container.java:2116)
at java.awt.Component.dispatchEvent(Component.java:4240)
at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1848)
at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:693)
at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:958)
at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:830)
at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:657)
at java.awt.Component.dispatchEventImpl(Component.java:4282)
at java.awt.Container.dispatchEventImpl(Container.java:2116)
at java.awt.Window.dispatchEventImpl(Window.java:2429)
at java.awt.Component.dispatchEvent(Component.java:4240)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)

Ich habe keine Ideen mehr, wie ich ein "überspannendes" gültiges Event simulieren soll. :/
Was mir noch einfallen würde wäre: Speichern der Events in eine Collection die ich dann nachher erst "feuere". So würde der parse-thread wenigstens nicht unterbrochen, dennoch würden dann "einen ganzen Haufen" Events fliegen. Also eigentlich auch keine Lösung.
 

Wildcard

Top Contributor
Youlian hat gesagt.:
Ich habe keine Ideen mehr, wie ich ein "überspannendes" gültiges Event simulieren soll. :/
Was mir noch einfallen würde wäre: Speichern der Events in eine Collection die ich dann nachher erst "feuere". So würde der parse-thread wenigstens nicht unterbrochen, dennoch würden dann "einen ganzen Haufen" Events fliegen. Also eigentlich auch keine Lösung.
5% hört sich doch schon ganz gut an :D
Das mit der Collection könnte durchaus funktionieren. Das eigentliche Problem ist vermutlich das repaint. Wenn diese Events aber sehr schnell aufeinander kommen, dann kann der EventDispatcher redundante paints aus der queue werfen und damit die benötigte Gesamtrechenzeit drücken.
Ich weiß nicht wie das ganze aussieht, aber falls es zu lange dauert bis man was sieht, könntest du auch hin und wieder ein Event 'freilassen' das schonmal etwas gezeichnet werden kann.
Ich würde dir gern mehr sagen, leider fehlen mir zu den Internas von JTextPane und StyledDocument jegliche Hintergrundinformation.
De facto: Hab ich noch nie benutzt :bae:
 
G

Guest

Gast
Es treten immer Exceptions auf, sogar wenn ich mir alle Events in einer Liste merke und sie nachträglich werfe. :/
Sobald ich die Events bzw. deren Feuerung abändere treten Exceptions (siehe oben) "tief" drinnen in der API auf, die ich nicht wirklich zurückverfolgen kann.
-> Ich werde wohl zu der alten Implementierung (Setzen der Farbe vor dem Zeichnen, immer alles Parsen) zurückgehen.
 

Wildcard

Top Contributor
Je nachdem was du alles brauchst könnte man das Ding auch selbst schreiben.
Aber wenn die Geschwindigkeit für dich noch im erträglichen Maß ist....
 

Youlian

Mitglied
Selbst schreiben hört sich jetzt zwar verlockend an, wegen der Übersichtlichkeit und Performance, aber ich bin mir ziemlich sicher, dass dabei auch unlösbare/schwere (für mich, als nicht java profi) Probleme auf mich zukommen.

Brauchen würde ich einfach nur eine grafische Komponente wie etwa JTextPane, JTextArea bei der ich einzelne Abschnitte, Zeichen verschiedenfarbig darstellen kann. (Ohne die oben beschriebenen Wechselwirkungen; AWT-Thread, Event werfen)
Wenn sich irgendwer findet der sowas machen könnte, währe ich natürlich dankbar - ich kann mit meinem jetzigen java/swing nicht.
 

kawrom

Mitglied
Hi,
Ich hatte auch das gleiche Problem wie Du mit der Performance:
bei ca 10 Zeilen Text ging das noch rel. schnell, aber bei 100 oder mehr Zeilen konnte man zusehen wie sich die Farbe der einzelnen chars aufbaut.

Hab dies aber dann doch gelöst:
beim parsen sammelst du nur die Farb- bzw. Font-Werte und die einzelnen Positionen für alle chars in einem Vector.
Nachdem der Parse-Vorgang abgeschlossen ist und du alle Werte berechnet hast,
läufst du den kompletten Vector in einer Schlefe durch und setzt die Werte der einzelnen chars
(setCharacterAttributes(beg, length, doc.getStyle(color), true); ... wobei length immer 1 beträgt)


... so einfach ist das!
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
MarvinsDepression Unbekanntes Zeichen in fremden Code wirft Fragen auf Allgemeine Java-Themen 4
S Zeichen | in regex Allgemeine Java-Themen 8
_user_q JavaFX Robot alle Unicode-Zeichen schreiben lassen können Allgemeine Java-Themen 12
T Komische Zeichen im Zusammenhang mit Serializable interface Allgemeine Java-Themen 13
M Checkstyle 100 Zeichen pro Zeile Allgemeine Java-Themen 11
T Letztes Zeichen eines Strings enfernen Allgemeine Java-Themen 14
Master3000 Komisches Zeichen als Ausgabe in der Konsole Allgemeine Java-Themen 20
M Warum gibt es Unterschiedliche Kommentar Zeichen Allgemeine Java-Themen 15
N Überprüfung ob ein bestimmtes Zeichen <1 mal vorkommt Allgemeine Java-Themen 2
N Prüfen, ob ein String 2x das selbe Zeichen hat Allgemeine Java-Themen 10
G Übermittlung zusätzlicher ASCII-Zeichen bei Übertragung von Dateiinhalt mit Xmodem - JAVA Allgemeine Java-Themen 9
R Wie bekomme ich das Zeichen 'digit' an vorderster Stelle Allgemeine Java-Themen 4
S [Regex] Nur diese Zeichen beachten Allgemeine Java-Themen 1
Bluedaishi Zeile um zeichen erweitern Allgemeine Java-Themen 9
N Datei Zeilenweise Einlesen, Versteckte Zeichen Allgemeine Java-Themen 5
Xge Replace x Zeichen aus String Allgemeine Java-Themen 2
S Java Editor Bekomme bei der Code-Vervollständigung die Zeichen &#8203; Allgemeine Java-Themen 3
E Compiler-Fehler Unicode Zeichen einlesen Allgemeine Java-Themen 1
U Variablen Stringarrays mit wenig verschiedenen Zeichen effizienter speichern Allgemeine Java-Themen 10
T xls-Datei per Apache Commons CsvParser einlesen UTF-8 Zeichen russische Zeichen Allgemeine Java-Themen 2
AssELAss String jeweils nach x Zeichen Zeilenumbruch Allgemeine Java-Themen 1
DStrohma Input/Output KeyEvent nur verarbeiten wenn es ein "sichtbares" Zeichen ist? Allgemeine Java-Themen 1
B In Java String ein + Zeichen Allgemeine Java-Themen 4
AssELAss Zeilenumbruch immer nach bestimmtem Zeichen Allgemeine Java-Themen 1
J Anzahl der Zeichen bei Eingabe begrenzen Allgemeine Java-Themen 5
V Tastendruck für UTF-8 Zeichen emulieren Allgemeine Java-Themen 4
B BufferedWriter in InputStream oder Zeichen-Stream in Byte-Stream Allgemeine Java-Themen 5
C Hex Zeichen ersetzen durch leer Zeichen Allgemeine Java-Themen 5
R Besondere Zeichen in Dateinamen Allgemeine Java-Themen 4
B Alt-Griechisch Zeichen in Dateien Allgemeine Java-Themen 2
G AES Verschlüsselung nur bis 63 Zeichen Länge Allgemeine Java-Themen 2
M Fehlende Zeichen beim Drucken mit PDFBox Allgemeine Java-Themen 10
J String nur erste Zeichen vergleichen Allgemeine Java-Themen 6
C Variablen $-Zeichen in String ersetzen Allgemeine Java-Themen 3
S String Zeichen für Zeichen vergleichen Allgemeine Java-Themen 4
L Problem bei ausführbarer jar Datei mit Unicode-Zeichen Allgemeine Java-Themen 4
S String in Double - letztes Zeichen fehlt Allgemeine Java-Themen 4
A Erstes Zeichen im String "toUpperCase"n Allgemeine Java-Themen 11
A Umwandlung von Text/Zeichen in Polynome Allgemeine Java-Themen 8
cedi int Zahl in ein ASCII zeichen umwandeln und dieses in ein externes Textfenster schreiben Allgemeine Java-Themen 6
K String: alle X Zeichen Zeilenumbruch Allgemeine Java-Themen 3
M Nach Programmdurchlauf werden Zeichen falsch dargestellt + Anderes Verhalten unter Windows Allgemeine Java-Themen 6
Zettelkasten Aus String bestimmtes Zeichen herausfinden Allgemeine Java-Themen 19
M Asterisk in String ("Egal-Zeichen") Allgemeine Java-Themen 4
V Chinesische Zeichen Escapen Allgemeine Java-Themen 4
I Teilweise falsche Darstellung jap. Zeichen im JEditorPane mit RTFEditorKit aus RTF-Datei Allgemeine Java-Themen 5
D Datei mit allen Ascii Zeichen Allgemeine Java-Themen 2
R Unsichtbare Zeichen Allgemeine Java-Themen 7
U Namen von Klassen haben $-Zeichen Allgemeine Java-Themen 5
P RegEx und $-Zeichen als Literal Allgemeine Java-Themen 5
neonfly Anzahl Zeichen pro Zeile auf der Konsole Allgemeine Java-Themen 8
C Strings zwischen 2 Zeichen auslesen Allgemeine Java-Themen 7
A Zeichen beim Eingeben in ein DOS-Fenster nicht anzeigen? Allgemeine Java-Themen 3
F Hexcode von ASCII Zeichen erhalten Allgemeine Java-Themen 2
J Mit Scanner-Klasse eine Datei zeilenweise einlesen und nur bestimmte Zeichen abfragen Allgemeine Java-Themen 11
V Dateien mit &-Zeichen im Namen öffnen Allgemeine Java-Themen 13
N String in einzelne Zeichen zerlegen Allgemeine Java-Themen 8
M Problem mit Zeichen aus einer Datei auslesen Allgemeine Java-Themen 2
T Shapes vergleichen? Zeichen erkennen? Allgemeine Java-Themen 7
G String.replaceall - mehrere Zeichen durch eines ersetzen Allgemeine Java-Themen 5
G Tschechische Zeichen in XML-Antwort Allgemeine Java-Themen 22
J Encoding und Gewinnung von Zeichen aus der Hexa-Darstellung Allgemeine Java-Themen 6
N Xor Warum kommt Flasches Zeichen in Java Allgemeine Java-Themen 36
S Stringarray splitten an unbekanntem Zeichen Allgemeine Java-Themen 7
A Dezimalzahlen: Komma-Zeichen Allgemeine Java-Themen 4
T Einzelnes Zeichen von der Tastatur einlesen, aber ohne Enter Allgemeine Java-Themen 4
S Was bedeutet dieser Zeichen Allgemeine Java-Themen 4
E Wie Zeichen eingeben mit Klasse Scanner? Allgemeine Java-Themen 5
S Zeichen, dass Programm noch läuft Allgemeine Java-Themen 3
M Anwendung nur einmal starten / Zeichen in String zählen Allgemeine Java-Themen 7
T [Regex] Zeichen ausschließen Allgemeine Java-Themen 8
Luma Unicode Steuerzeichen von druckbaren Zeichen trennen Allgemeine Java-Themen 10
M JTable: Anzahl Zeichen bei Eingabe Allgemeine Java-Themen 2
G String parsen und Problem mit escaped zeichen Allgemeine Java-Themen 4
Z Letztes zeichen eines strings löschen Allgemeine Java-Themen 3
A bestimmte Zeichen aus einem String auslesen Allgemeine Java-Themen 2
L unicode-zeichen in ein txt-File schreiben Allgemeine Java-Themen 3
J Problem mit nichtlateinischen Zeichen Allgemeine Java-Themen 2
B String + Zeilenumbruch nach X-Zeichen Allgemeine Java-Themen 4
M Nach 4 Zeichen Fokus ändern Allgemeine Java-Themen 2
oliver1974 Wie ResourceBundles mit Unicode Zeichen korrekt einlesen? Allgemeine Java-Themen 4
E Alarm ausgeben (ASCII Zeichen 7) über Lautsprecher Allgemeine Java-Themen 11
G Alle Zeichen des Alphabets ausgeben Allgemeine Java-Themen 4
K String-Objekt mit zig tausend Zeichen Allgemeine Java-Themen 12
T Muster/Zeichen/Texterkennung auf einem Image Allgemeine Java-Themen 9
P Regulärer Ausdruck um sich wiederholende Zeichen zu finden. Allgemeine Java-Themen 9
O Split methode tut bei Zeichen "\", "\\" Allgemeine Java-Themen 7
H Unicode Darstellung in Java, spezielles Zeichen gesucht Allgemeine Java-Themen 4
S Unicode-Zeichen erstellen/ Kodierung Allgemeine Java-Themen 4
J RegEx: "wenn zeichen folgen ersetze x mit y, sonst mit Allgemeine Java-Themen 2
Z Zeichen/char in einer Datei löschen Allgemeine Java-Themen 6
I $ zeichen im class-namen Allgemeine Java-Themen 4
S ￾ Zeichen umwandeln in ü per .replace(); Allgemeine Java-Themen 6
N Zeilenumbruch in String nach jeweils x Zeichen einfügen? Allgemeine Java-Themen 6
D gewisse Zeichen sind nach dem entschlüsseln anders Allgemeine Java-Themen 2
G Wandeln von Char Wert in Zeichen? Allgemeine Java-Themen 2
G subString() aber nicht auf Länge sondern auf Zeichen Allgemeine Java-Themen 3
L Hex --> Dezimal --> Zeichen Allgemeine Java-Themen 7
M Codepage Problem (Vertauscht Zeichen beim Lesen aus Datei) Allgemeine Java-Themen 3
C Unicode für Promille-Zeichen Allgemeine Java-Themen 5

Ähnliche Java Themen

Neue Themen


Oben