G
Gastredner
Gast
Hallo,
ich arbeite derzeit an einer Oberflächenkomponente, die mir beim Einbau in einer Applikation die Möglichkeit geben soll, Jar-Archive per Dialog auszuwählen und alle dort enthaltenen LookAndFeels während der Laufzeit auszulesen und anzuwenden.
Ein erstes Grundgerüst steht soweit und funktioniert auch - überwiegend. Ich habe ein hartnäckiges Problem mit einer NullPointerException bei den Business-LookAndFeels aus dem Substance-Archiv (SubstanceBusinessLookAndFeel, SubstanceBusinessBlueSteelLookAndFeel, SubstanceBusinessBlackSteelLookAndFeel). Interessanterweise allerdings auch wirklich nur mit diesen dreien - alle anderen LaFs aus der Substance-Bibliothek funktionieren tadellos.
Der StackTrace der NPE:
Dies ist übrigens die Methode aus der Klasse ImageWrapperDecorationPainter.java:
[JAVA=323] protected Image getColorizedTile(SubstanceColorScheme scheme) {
Image result = this.colorizedTileMap.get(scheme.getDisplayName());
if (result == null) {
BufferedImage tileBi = new BufferedImage(this.originalTile
.getWidth(null), this.originalTile.getHeight(null),
BufferedImage.TYPE_INT_ARGB);
tileBi.getGraphics().drawImage(this.originalTile, 0, 0, null);
result = SubstanceImageCreator.getColorSchemeImage(tileBi, scheme,
0.0f);
this.colorizedTileMap.put(scheme.getDisplayName(), result);
}
return result;
}[/code]
Ich kann mit diesem Fehler nichts anfangen, bzw. verstehe ich nicht, wieso er nur bei der der 2 LookAndFeels aus der Bibliothek auftritt.
Desweiteren habe ich Probleme mit dem Laden eines einzelnen LookAndFeels aus einem .jar: Obwohl der Vorgang der gleiche ist wie beim Laden aller LaFs aus der gleichen Bibliothek, ist die VM anschließend nicht in der Lage, die neben der LookAndFeel-Klasse selbst benötigten Klassen aus dem Archiv zu laden. Der Code:
Kurz zum Vorgang: Es wird zuerst überprüft, ob die Klasse bereits schonmal geladen worden ist. Sollte dem nicht so sein, so wird der Pfad zum Jar-Archiv zum erzeugen eines URL-Objektes genutzt und einem URLClassLoader übergeben, mit dem anschließend die gewünschte Klasse geladen wird. Dem aktuellen Thread wird anschließend der neue ClassLoader mit dem Verweis auf das Archiv bekannt gemacht und das geladene LookAndFeel zurückgegeben.
Der Vorgang wird beim Laden aller LaFs aus einem Archiv bzw. aus einer Liste von Archiven dadurch ergänzt, dass das Archiv nach Dateien mit der Endung "LookAndFeel.class" durchsucht wird. Die gefundenen Dateien werden in einer Liste gespeichert und anschließend durch den URLClassLoader geladen und instantiiert, bevor der ClassLoader dem Thread übergeben und die Liste der LaF-Objekte zurückgegeben wird.
Bei Letzterem funktioniert dies - bis auf die Probleme mit den drei Substance-LaFs und dem FH-LookAndFeel - tadellos, der oben gepostete Code erzeugt hindessen den angesprochenen Fehler:
Abgesehen von den Problemen frage ich mich auch, inwiefern mein Vorgehen beim Laden wonöglich suboptimal bzw. fehleranfällig ist. Für etwaige Verbesserungsvorschläge wäre ich daher dankbar.
Gruß
~Gastredner
ich arbeite derzeit an einer Oberflächenkomponente, die mir beim Einbau in einer Applikation die Möglichkeit geben soll, Jar-Archive per Dialog auszuwählen und alle dort enthaltenen LookAndFeels während der Laufzeit auszulesen und anzuwenden.
Ein erstes Grundgerüst steht soweit und funktioniert auch - überwiegend. Ich habe ein hartnäckiges Problem mit einer NullPointerException bei den Business-LookAndFeels aus dem Substance-Archiv (SubstanceBusinessLookAndFeel, SubstanceBusinessBlueSteelLookAndFeel, SubstanceBusinessBlackSteelLookAndFeel). Interessanterweise allerdings auch wirklich nur mit diesen dreien - alle anderen LaFs aus der Substance-Bibliothek funktionieren tadellos.
Der StackTrace der NPE:
Code:
Exception occurred during event dispatching:
java.lang.NullPointerException
at org.jvnet.substance.painter.decoration.ImageWrapperDecorationPainter.getColorizedTile(ImageWrapperDecorationPainter.java:326)
at org.jvnet.substance.painter.decoration.ImageWrapperDecorationPainter.tileArea(ImageWrapperDecorationPainter.java:254)
at org.jvnet.substance.painter.decoration.ImageWrapperDecorationPainter.paintExtraBackground(ImageWrapperDecorationPainter.java:218)
at org.jvnet.substance.painter.decoration.ImageWrapperDecorationPainter.paintDecorationArea(ImageWrapperDecorationPainter.java:109)
at org.jvnet.substance.painter.utils.DecorationPainterUtils.paintDecorationBackground(DecorationPainterUtils.java:214)
at org.jvnet.substance.painter.utils.DecorationPainterUtils.paintDecorationBackground(DecorationPainterUtils.java:174)
at org.jvnet.substance.painter.utils.BackgroundPaintingUtils.update(BackgroundPaintingUtils.java:114)
at org.jvnet.substance.SubstanceMenuBarUI.__org__jvnet__substance__SubstanceMenuBarUI__update(SubstanceMenuBarUI.java:96)
at org.jvnet.substance.SubstanceMenuBarUI.__org__jvnet__substance__SubstanceMenuBarUI__container__update(SubstanceMenuBarUI.java)
at org.jvnet.substance.SubstanceMenuBarUI.update(SubstanceMenuBarUI.java)
at javax.swing.JComponent.paintComponent(JComponent.java:763)
at javax.swing.JComponent.paint(JComponent.java:1029)
at javax.swing.JComponent.paintChildren(JComponent.java:864)
at javax.swing.JComponent.paint(JComponent.java:1038)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:567)
at javax.swing.JComponent.paintChildren(JComponent.java:864)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5131)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1475)
at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1406)
at javax.swing.RepaintManager.paint(RepaintManager.java:1220)
at javax.swing.JComponent.paint(JComponent.java:1015)
at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:21)
at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60)
at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97)
at java.awt.Container.paint(Container.java:1780)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:714)
at javax.swing.RepaintManager.seqPaintDirtyRegions(RepaintManager.java:694)
at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:128)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:178)
at java.awt.Dialog$1.run(Dialog.java:1045)
at java.awt.Dialog$3.run(Dialog.java:1097)
at java.security.AccessController.doPrivileged(Native Method)
at java.awt.Dialog.show(Dialog.java:1095)
at java.awt.Component.show(Component.java:1563)
at java.awt.Component.setVisible(Component.java:1515)
at java.awt.Window.setVisible(Window.java:841)
at java.awt.Dialog.setVisible(Dialog.java:985)
at de.snk.snkomponents.plafchooser.Test.openDialog(Test.java:130)
at de.snk.snkomponents.plafchooser.Test.actionPerformed(Test.java:149)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
at java.awt.Component.processMouseEvent(Component.java:6263)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
at java.awt.Component.processEvent(Component.java:6028)
at java.awt.Container.processEvent(Container.java:2041)
at java.awt.Component.dispatchEventImpl(Component.java:4630)
at java.awt.Container.dispatchEventImpl(Container.java:2099)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
at java.awt.Container.dispatchEventImpl(Container.java:2085)
at java.awt.Window.dispatchEventImpl(Window.java:2475)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
[JAVA=323] protected Image getColorizedTile(SubstanceColorScheme scheme) {
Image result = this.colorizedTileMap.get(scheme.getDisplayName());
if (result == null) {
BufferedImage tileBi = new BufferedImage(this.originalTile
.getWidth(null), this.originalTile.getHeight(null),
BufferedImage.TYPE_INT_ARGB);
tileBi.getGraphics().drawImage(this.originalTile, 0, 0, null);
result = SubstanceImageCreator.getColorSchemeImage(tileBi, scheme,
0.0f);
this.colorizedTileMap.put(scheme.getDisplayName(), result);
}
return result;
}[/code]
Ich kann mit diesem Fehler nichts anfangen, bzw. verstehe ich nicht, wieso er nur bei der der 2 LookAndFeels aus der Bibliothek auftritt.
Desweiteren habe ich Probleme mit dem Laden eines einzelnen LookAndFeels aus einem .jar: Obwohl der Vorgang der gleiche ist wie beim Laden aller LaFs aus der gleichen Bibliothek, ist die VM anschließend nicht in der Lage, die neben der LookAndFeel-Klasse selbst benötigten Klassen aus dem Archiv zu laden. Der Code:
Java:
private Map<String, LookAndFeel> loaded; // Enthält bereits geladene LaFs
public LookAndFeel loadLookAndFeel(String className, String jar) throws LookAndFeelLoaderException {
LookAndFeel laf = loaded.get(className);
if (laf == null) {
try {
URL[] jars = { new URL("jar:file:" + jar + "!/") };
URLClassLoader cl = new URLClassLoader(jars);
Class<LookAndFeel> c = (Class<LookAndFeel>) cl.loadClass(className);
if (isValidPLAFClass(c)) {
laf = c.newInstance();
loaded.put(className, laf);
Thread.currentThread().setContextClassLoader(cl);
} else {
throw new LookAndFeelLoaderException("Can not instantiate class \"" + className + "\"!", Reason.ABSTRACT_OR_INTERFACE);
}
} catch (MalformedURLException e) {
throw new LookAndFeelLoaderException("The URL for \"" + jar + "\" is not valid!", Reason.MALFORMED_URL);
} catch (NoClassDefFoundError e) {
throw new LookAndFeelLoaderException("The class \"" + className + "\" was not found in archive \"" + jar + "\"!", Reason.WRONG_CLASSNAME);
} catch (ClassNotFoundException e) {
throw new LookAndFeelLoaderException("The class \"" + className + "\" was not found in archive \"" + jar + "\"!", Reason.WRONG_CLASSNAME);
} catch (IllegalAccessException e) {
throw new LookAndFeelLoaderException(e, Reason.OTHER);
} catch (InstantiationException e) {
throw new LookAndFeelLoaderException(e, Reason.OTHER);
}
}
return laf;
}
private boolean isValidPLAFClass(Class<LookAndFeel> c) {
return !c.isInterface() && !Modifier.isAbstract(c.getModifiers()) && Modifier.isPublic(c.getModifiers()) && c.getSimpleName().endsWith("LookAndFeel");
}
Der Vorgang wird beim Laden aller LaFs aus einem Archiv bzw. aus einer Liste von Archiven dadurch ergänzt, dass das Archiv nach Dateien mit der Endung "LookAndFeel.class" durchsucht wird. Die gefundenen Dateien werden in einer Liste gespeichert und anschließend durch den URLClassLoader geladen und instantiiert, bevor der ClassLoader dem Thread übergeben und die Liste der LaF-Objekte zurückgegeben wird.
Bei Letzterem funktioniert dies - bis auf die Probleme mit den drei Substance-LaFs und dem FH-LookAndFeel - tadellos, der oben gepostete Code erzeugt hindessen den angesprochenen Fehler:
Code:
UIDefaults.getUI() failed: no ComponentUI class for: javax.swing.JList[ /* Die ganzen Eigenschaften... */ ]
java.lang.Error
at javax.swing.UIDefaults.getUIError(UIDefaults.java:711)
at javax.swing.MultiUIDefaults.getUIError(MultiUIDefaults.java:133)
at javax.swing.UIDefaults.getUI(UIDefaults.java:741)
at javax.swing.UIManager.getUI(UIManager.java:1017)
at javax.swing.JList.updateUI(JList.java:508)
at javax.swing.JList.<init>(JList.java:403)
at javax.swing.JList.<init>(JList.java:447)
at de.snk.snkomponents.plafchooser.LoaderTest$2.run(LoaderTest.java:57)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:199)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Gruß
~Gastredner
Zuletzt bearbeitet von einem Moderator: