Java. Swing. Dem Wahnsinn nahe.

Seit Swing 1.0.2, als das Package noch com.sun.java.swing hieß und Java 1.1 gerade der heiße Scheiß war, programmiere ich UIs mit Java und Swing. Es ist so eine Art Hassliebe. Nach wie vor halte ich es für den einfachsten und besten Weg, Cross-Platform-Anwendungen zu schreiben, die mehr oder weniger problemlos unter Windows und Linux und MacOS funktionieren. Und an sonnigen Tagen auch unter AIX und Solaris.

Aber manchmal…manchmal…graue Haare, Stirnrunzeln beim Debugging, dem Wahnsinn nahe. Ich baue gerade an einem kleinen Projekt dessen tieferer Sinn oder Unsinn hier nichts zur Sache tun soll. Jedenfalls wird dort als Anzeigekomponente die allseits beliebe JEditorPane mit HTML-Inhalt verwendet. Das ist von jeher etwas kitzelig weil ein etwas merkwürdiges HTML-3.2-Sub-und-Superset-mit-etwas-CSS unterstützt wird, und man sollte sehr genau wissen welches HTML man reinsteckt und was unfallfrei gerendert werden kann. Immer spannend war das Thema Grafiken. Im Prinzip sollte es ja ein img-Tag mit passender URL dahinter tun. Blabla.class.getResource(“/schnickschnack.png”) liefert ja schon eine lokale File-URL zurück, was kann da schon schiefgehen.

Eine ganze Menge. Und was ist, wenn man gar keine Datei hat, sondern ein beliebiges Image in-memory? Weil das so ist, haben schlaue Menschen einen Weg ersonnen, wie man der JEditorPane – oder besser gesagt dem HTMLDocument, das über den HTMLEditorKit beim ContentType “text/html” bekanntlich entsteht – ein beliebiges Image unterjubeln kann, indem man es in einen “imageCache” unter der im img-Tag hinterlegten URL steckt.

Hier ein Link zu Sourcecode, der illustriert, wie das prinzipiell geht. Sehr heikel, weil es sich auf ein Implementierungsdetail verlässt, aber Swing ist bekanntlich tot…äh…stabil, und so wird das wohl auch in Zukunft problemlos funktionieren. Dachte ich.

Wenn man nun aber obigen Sourcecode mal in der IDE der Wahl compiliert und zur Ausführung bringt, erlebt man leider eine Überraschung: mit Java 7 funktioniert das noch problemlos, mit Java 8 und neuer aber nicht. Ein beherztes Debugging an der richtigen Stelle – javax.swing.text.html.ImageView.loadImage – brachte keinen Aufschluss – das Image wird korrekt aus dem Cache geholt, seine Größe wird inspiziert, es wird layoutet, und dann…wird nichts angezeigt.

Ich will es nicht zu spannend machen, denn es gibt einen Workaround. Auch wenn ich gerade überhaupt nicht verstehe, warum der was ändert, weil genau das, was er eventuell ändern könnte, im Debugging nicht nach dem Problem ausgesehen hat.

Wenn man die Zeile

"<img src=\""+localImageSrc+"\">\n" +

ändert in

"<img src=\""+localImageSrc+"\" width=100 height=50>\n" +

dann funktioniert es plötzlich prima von Java 7 bis einschließlich Java 16.

Wer auch immer das im Detail analysieren will – Freiwillige vor.