Fehlersuche bei SWT/JFreeChart/Extended Desktop

crkn

Grünschnabel
Hi Leute,

ich habe ein Programm übertragen bekommen bei dem SWT & JFreeChart mehr oder weniger gut eingesetzt wurden. Selber hatte ich nur mit dem AWT und Swing zu tun, mit SWT und JFreeChart noch gar nicht. Jedenfalls läuft die Software inzwischen schon deutlich stabiler als vorher, aber ein paar Sachen bleiben hartnäckig vorhanden:

a) Anzeigefehler bei erweitertem Desktop:
Wenn man die GUI von dem "primären" Monitor auf den "erweiterten" Monitor verschiebt, treten bei einer ScrolledComposite (die mehrere Charts enthält) Anzeigefehler in der Form vor, das alle Charts nach dem hoch- oder runterscrollen den selben Chart anzeigen (also auch Beschriftung usw., praktisch 1 Chart wird x-mal angezeigt anstatt x verschiedener Charts). Auf dem "primären" Monitor ist das nicht zu beobachten.
Ist das nun ein SWT-Problem irgendwie im Zusammenhang mit "Display"? Oder eher bei JFreeChart zu suchen?

b) Regelmässige aber nicht immer auftretende ConcurrentModificationException's alternativ auch mal NullPointerException's beim Einlesen von Dateien und darauf folgenden Chart-Aktualisierungen:
Code:
Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
	at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
	at java.util.AbstractList$Itr.next(Unknown Source)
	at java.util.Collections$UnmodifiableCollection$1.next(Unknown Source)
	at org.jfree.chart.plot.XYPlot.drawDomainMarkers(XYPlot.java:4015)
	at org.jfree.chart.plot.XYPlot.draw(XYPlot.java:3378)
	at org.jfree.chart.JFreeChart.draw(JFreeChart.java:1235)
	at org.jfree.chart.ChartPanel.paintComponent(ChartPanel.java:1668)
	at javax.swing.JComponent.paint(Unknown Source)
	at javax.swing.JComponent.paintToOffscreen(Unknown Source)
	at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
	at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
	at javax.swing.BufferStrategyPaintManager.paint(Unknown Source)
	at javax.swing.RepaintManager.paint(Unknown Source)
	at javax.swing.JComponent._paintImmediately(Unknown Source)
	at javax.swing.JComponent.paintImmediately(Unknown Source)
	at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
	at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
	at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source)
	at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
	at java.awt.event.InvocationEvent.dispatch(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)

Dahinter vermute ich ja irgendwie diese UI-Thread Sache von SWT, auf die ich bei der Suche bisher stieß. Vor allem da
c) die Software auch "Invalid Thread Access Exceptions" hatte. Die habe ich zwar rausbekommen, aber erstmal auch nur durch bloßes auskommentieren der Statements ( ;) ), da die eigentlich völlig überflüssig waren. So etwas wie asyncExec() oder syncExec() war also erstmal nicht nötig.


Irgendwelche Anregungen oder Such-Stichwörter? Bei der inzwischen schon längeren Internetrecherche kommt irgendwie nichts bei rum, was wirklich weiterhilft. Aber vermutlich suche ich auch einfach nach dem Falschen.

Hat btw. einer einen guten Link wo das UI-Thread-Konzept von SWT ausführlicher erklärt wird. Die Suchergebnisse liefern i.d.R. nur SWT-Einführungen bei denen Elemente und Aufbau einer GUI beschrieben sind. Und bei JFreeChart gibts kaum was im Netz, aber dafür dieses eine Buch da, richtig?

Gruß,
crkn
 
Liegt der SWT-Teil von JFreeChart immer noch im experimental Package? Vor 3 Jahren war das ganze noch recht buggy.

Die ConcurrentModificationException kommt wahrscheinlich daher, dass du zu schnell und unsynchronisiert Daten in den Chart schreibst. Wie sieht denn die NullPointerException aus? Die Exception wird ausgelöst, wenn eine Collection gleichzeitig verändert und währenddessen darüber iteriert wird.

Ein InvalidThreadAccess tritt immer dann auf, wenn in SWT aus einem anderen als dem GUI-Thread auf die GUI zugegriffen wird. Das Prinzip ist sehr einfach: In SWT gibt es nur einen GUI-Thread. Will man aus einem anderen Thread auf die GUI zugreifen muss man das mit asyn/syncExec machen. Dabei darauf achten, dass die auszuführenden Operationen nicht zeitintensiv ist, weil sonst die GUI nicht mehr reagiert.
 
Liegt der SWT-Teil von JFreeChart immer noch im experimental Package? Vor 3 Jahren war das ganze noch recht buggy.

Öhm, keine Ahnung. Das ist hier mit einem Konvertieren gemäß http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/ConvertbetweenSWTImageandAWTBufferedImage.htm "gelöst" worden.


Die ConcurrentModificationException kommt wahrscheinlich daher, dass du zu schnell und unsynchronisiert Daten in den Chart schreibst. Wie sieht denn die NullPointerException aus? Die Exception wird ausgelöst, wenn eine Collection gleichzeitig verändert und währenddessen darüber iteriert wird.

Oh, neuerdings wechseln sich Concurrent und IndexOutOfBounds ab anstatt der NullPointerException. Jedenfalls sieht die zweite wie folgt aus:

Code:
Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
	at java.util.ArrayList.RangeCheck(Unknown Source)
	at java.util.ArrayList.get(Unknown Source)
	at org.jfree.data.xy.XYSeriesCollection.getX(XYSeriesCollection.java:319)
	at org.jfree.data.xy.AbstractXYDataset.getXValue(AbstractXYDataset.java:75)
	at org.jfree.chart.renderer.xy.XYLineAndShapeRenderer.drawSecondaryPass(XYLineAndShapeRenderer.java:1139)
	at org.jfree.chart.renderer.xy.XYLineAndShapeRenderer.drawItem(XYLineAndShapeRenderer.java:925)
	at org.jfree.chart.plot.XYPlot.render(XYPlot.java:3738)
	at org.jfree.chart.plot.XYPlot.draw(XYPlot.java:3310)
	at org.jfree.chart.JFreeChart.draw(JFreeChart.java:1235)
	at org.jfree.chart.ChartPanel.paintComponent(ChartPanel.java:1668)
	at javax.swing.JComponent.paint(Unknown Source)
	at javax.swing.JComponent.paintToOffscreen(Unknown Source)
	at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
	at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
	at javax.swing.BufferStrategyPaintManager.paint(Unknown Source)
	at javax.swing.RepaintManager.paint(Unknown Source)
	at javax.swing.JComponent._paintImmediately(Unknown Source)
	at javax.swing.JComponent.paintImmediately(Unknown Source)
	at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
	at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
	at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source)
	at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
	at java.awt.event.InvocationEvent.dispatch(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)


Ein InvalidThreadAccess tritt immer dann auf, wenn in SWT aus einem anderen als dem GUI-Thread auf die GUI zugegriffen wird. Das Prinzip ist sehr einfach: In SWT gibt es nur einen GUI-Thread. Will man aus einem anderen Thread auf die GUI zugreifen muss man das mit asyn/syncExec machen. Dabei darauf achten, dass die auszuführenden Operationen nicht zeitintensiv ist, weil sonst die GUI nicht mehr reagiert.

Da ist nun die Frage, welcher Thread ist der GUI-Thread, wann wird er erzeugt und wo? Und dann gibts immer den GUI-Thread und mindestens einen Thread für das Programm?
 
Zuletzt bearbeitet:
Warum nehmt ihr denn nicht die SWT-Integration von JFreeChart. Sieht sehr fehleranfällig aus dieser Umwandlungscode..

Es gibt natürlich immer einen GUI-Thread für SWT. Sofern man nicht selber explizit einen anderen Thread startet, benötigt man das sync/asyncExec nicht. Wenn ein eigener Thread gestartet wurde, dann mußt du die entsprechend benutzen. Man sieht es eben u.a. an der InvalidThreadAcessException.
 
Warum nehmt ihr denn nicht die SWT-Integration von JFreeChart. Sieht sehr fehleranfällig aus dieser Umwandlungscode..

Wie gesagt, die Software wurde übernommen/übertragen. Von einer SWT-Integration habe ich aber auch noch nix gelesen bei jfree.org? Dafür aber tausend Links bei Google die ähnlich "komisch" konvertieren, so daß schnell klar war, wovon da "kopiert" wurde. Naja, aber wenn die Integration eh noch als "experimental" läuft, weiß ich noch nicht ob es ohnehin mehr Sinn macht SWT durch Swing zu ersetzen.


Man sieht es eben u.a. an der InvalidThreadAcessException.

Explizite weitere Threads gab es eigentlich nie. Aber naja, die Exception kam ja auch nur am Anfang und tritt nun nicht mehr auf.


Die ConcurrentModificationException, IndexOutOfBoundsException und eine IllegalArgumentException:
Code:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Series index out of bounds
	at org.jfree.data.xy.XYSeriesCollection.getSeries(XYSeriesCollection.java:248)
	at org.jfree.data.xy.XYSeriesCollection.getSeriesKey(XYSeriesCollection.java:292)
	at org.jfree.chart.labels.AbstractXYItemLabelGenerator.createItemArray(AbstractXYItemLabelGenerator.java:278)
	at org.jfree.chart.labels.AbstractXYItemLabelGenerator.generateLabelString(AbstractXYItemLabelGenerator.java:248)
	at org.jfree.chart.labels.StandardXYToolTipGenerator.generateToolTip(StandardXYToolTipGenerator.java:165)
	at org.jfree.chart.renderer.xy.AbstractXYItemRenderer.addEntity(AbstractXYItemRenderer.java:1710)
	at org.jfree.chart.renderer.xy.XYLineAndShapeRenderer.drawSecondaryPass(XYLineAndShapeRenderer.java:1206)
	at org.jfree.chart.renderer.xy.XYLineAndShapeRenderer.drawItem(XYLineAndShapeRenderer.java:925)
	at org.jfree.chart.plot.XYPlot.render(XYPlot.java:3738)
	at org.jfree.chart.plot.XYPlot.draw(XYPlot.java:3310)
	at org.jfree.chart.JFreeChart.draw(JFreeChart.java:1235)
	at org.jfree.chart.ChartPanel.paintComponent(ChartPanel.java:1668)
	at javax.swing.JComponent.paint(Unknown Source)
	at javax.swing.JComponent.paintToOffscreen(Unknown Source)
	at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
	at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
	at javax.swing.BufferStrategyPaintManager.paint(Unknown Source)
	at javax.swing.RepaintManager.paint(Unknown Source)
	at javax.swing.JComponent._paintImmediately(Unknown Source)
	at javax.swing.JComponent.paintImmediately(Unknown Source)
	at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
	at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
	at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source)
	at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
	at java.awt.event.InvocationEvent.dispatch(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)

treten nun "nur" noch unregelmässig auf. Dabei muss man aber noch erwähnen, dass die zu keinem sichtbaren Fehler führen. Also die Anwendung bleibt nicht hängen und die Charts sehen auch korrekt aus.
 
Zurück