SynthLookAndFeel

ThommiR

Mitglied
Hallo zusammen,

ich hoffe, ihr könnt mir ein paar Hilfestellungen und/oder Ansätze für die weitere Recherche geben. Ich bin auf der Suche nach einer Möglichkeit, die Farbe der Titelleiste in einem JFrame zu individualisieren (Programmierung in Eclipse Nova mit WindowBuilder in Windows 10). Da ich nicht glaube, dass ich allzu schnell durchblicke, wie ich einen eigenen Look&Feel schreiben könnte, habe ich mich auf die Recherche zum SynthLookAndFeel gestürzt.

Ich hatte dann erst mal versucht, eine Beispiel-XML-Datei einzulesen, bekomme aber durch die Anweisung

lookAndFeel.load(SepaRechner3.class.getResourceAsStream(laf.getPath()), SepaRechner3.class);
eine IllegalArgumentException (Überprüfung, dass auf die XML-Datei laf zugegriffen werden kann, war positiv) und finde nicht raus, warum.
Vielleicht habt ihr da ja auch einen schnellen Blick, woran das liegen könnte...

Jedenfalls habe ich dann angefangen zu schauen, wie ich den SynthLookAndFeel ohne XML-Datei erstellen könnte, wobei ich zum Schluss kam, dass ich eine SynthStyleFactory erstellen muss, für welche ich wiederum einen SynthStyle aufrufe. Für diesen Prozess habe ich einige Beispiel-Codes gefunden, aber immer erscheint es mir so, als ob auf vorhandene SynthStyles zurückgegriffen wird und erklärt mir nicht, wie ich einen SynthStyle selbst definieren könnte.
Das ist der Punkt, an dem ich hauptsächlich hoffe, dass ihr mir mit eurer Erfahrung helfen könnt. Ich war ja überrascht, wie wenig präsent das Thema im Internet ist, bis auf die Doc, in der die Information scheinbar auch bei der Methode getSynthStyle(...) endet.
Kennt sich hier jemand damit aus?


Vielen Dank und viele Grüße,

Thommi
 

ThommiR

Mitglied
Das stimmt natürlich, sorry. Ich hatte daran nicht gedacht, weil ich gehofft hatte, dass in der Anweisung selbst vielleicht ein Fehler für das geübte Auge schnell in selbiges fällt.

java.lang.IllegalArgumentException: You must supply an InputStream, StyleFactory and Class or URL
at javax.swing.plaf.synth.SynthParser.parse(Unknown Source)
at javax.swing.plaf.synth.SynthLookAndFeel.load(Unknown Source)
at iban.SepaRechner3.initLookAndFeel(SepaRechner3.java:65)
at iban.SepaRechner3.<init>(SepaRechner3.java:96)
at iban.SepaRechner3$1.run(SepaRechner3.java:83)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(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)


Da hier die wesentliche Aussage "Unknown Source" lautet, hat mir das bisher nicht viel geholfen. Die Positionsangaben bei ein paar Fehlerstellen beziehen sich alle auf die Zeilen, in denen die Anweisung oder umgebende Methoden aufgerufen werden. Die Doku sagt ja auch nur, dass die IllegalArgumentException geworfen wird, wenn der übergebene String oder die übergebene Klasse null sind. Wenn dieses der Fall ist, ist es aber recht einleuchtend, dass dabei eine "Unknown Source" entsteht.

Gerade habe ich aber eine Vermutung/Befürchtung, wo der Fehler liegen könnte. Die genannte Anweisung sitzt innerhalb einer Methode initLookAndFeel(), deren Zweck wohl aus dem Namen ersichtlich ist. SepaRechner3 ist die Klasse für den JFrame (davon wird dann eine Instanz erzeugt, die den eigentlichen Frame abbildet), in dem ich den LookAndFeel aufrufen will, um das Aussehen zu verändern, indem ich initLookAndFeel() aufrufe. Kann es sein, dass das Ganze nicht klappt, weil ich unbedacht das erzeuge, was Excel einen Zirkelbezug nennt? Wie kann ich das umgehen? Genügt es, wenn ich initLookAndFeel() nicht innerhalb des Klassenaufrufs von SepaRechner3 positioniere, sondern erst nach der Initialisierung des Frames? Aber irgendwo hatte ich aufgeschnappt, dass das LaF besser angewendet wird, bevor andere Instanzen wie Buttons etc. aufgerufen werden...


Mein Kopf dreht sich gerade ein wenig... Ich hoffe, das hilft erst mal weiter, bevor ich den kompletten Code poste...

Viele Grüße,

Thommi
 

Joose

Top Contributor
Das "Unknown Source" bedeutet nur das er den SourceCode zu diesen Klassen/Methoden nicht finden kann. Diese könntest du aber wahrscheinlich auch online nachschauen.
Ich würde dir raten mal den Source von "javax.swing.plaf.synth.SynthLookAndFeel.load" und "javax.swing.plaf.synth.SynthParser.parse" anzuschauen wann die Exception geworfen wird.
Was übergibst du? Kann es sein das SepaRechner3.class.getResourceAsStream(laf.getPath()) null liefert?

Gerade habe ich aber eine Vermutung/Befürchtung, wo der Fehler liegen könnte. Die genannte Anweisung sitzt innerhalb einer Methode initLookAndFeel(), deren Zweck wohl aus dem Namen ersichtlich ist. SepaRechner3 ist die Klasse für den JFrame (davon wird dann eine Instanz erzeugt, die den eigentlichen Frame abbildet), in dem ich den LookAndFeel aufrufen will, um das Aussehen zu verändern, indem ich initLookAndFeel() aufrufe. Kann es sein, dass das Ganze nicht klappt, weil ich unbedacht das erzeuge, was Excel einen Zirkelbezug nennt? Wie kann ich das umgehen? Genügt es, wenn ich initLookAndFeel() nicht innerhalb des Klassenaufrufs von SepaRechner3 positioniere, sondern erst nach der Initialisierung des Frames? Aber irgendwo hatte ich aufgeschnappt, dass das LaF besser angewendet wird, bevor andere Instanzen wie Buttons etc. aufgerufen werden...
Hm ich bin mir nicht ganz sicher ob du mit "Zirkelbezug" eine Rekursion meinst, dann würde aber eine andere Exception fliegen.
Klar das LaF sollte angepasst werden bevor du etwas anzeigst, praktisch wäre es also diese Methode sogar noch vor dem JFrame aufzurufen (in der main-Methode zum Beispiel)
 

ThommiR

Mitglied
Hm ich bin mir nicht ganz sicher ob du mit "Zirkelbezug" eine Rekursion meinst, dann würde aber eine andere Exception fliegen.
Wohl wahr...

Klar das LaF sollte angepasst werden bevor du etwas anzeigst, praktisch wäre es also diese Methode sogar noch vor dem JFrame aufzurufen (in der main-Methode zum Beispiel)
Ich hatte wohl angenommen, dass ein Frame existieren muss, um ein LaF anzuwenden, was dann wohl nicht der Fall ist. Das verhindert aber zumindest noch nicht das Problem.

Ich würde dir raten mal den Source von "javax.swing.plaf.synth.SynthLookAndFeel.load" und "javax.swing.plaf.synth.SynthParser.parse" anzuschauen wann die Exception geworfen wird.
Was übergibst du? Kann es sein das SepaRechner3.class.getResourceAsStream(laf.getPath()) null liefert?
Load wirft die IllegalArgumentException, wenn (resourceBase == null) ist, greift aber auf parse zurück, welches ebenfalls die IllegalArgumentException wirft, sowohl bei (input == null), als auch bei (resourceBase == 0).
GetResourceAsStream ist zu finden in java.lang.Class mit folgendem Code:
Java:
public InputStream getResourceAsStream(String name) {
        name = resolveName(name);
        ClassLoader cl = getClassLoader0();
        if (cl==null) {
            // A system class.
            return ClassLoader.getSystemResourceAsStream(name);
        }
        return cl.getResourceAsStream(name);
    }
Ich sehe nicht, dass die Methode vorsieht, null zu liefern.
Ich hatte ja bisher in meiner Unwissenheit eher die Vermutung, dass SepaRechner3.class aus irgendeinem Grund nicht funktioniert, aber ich weiß momentan nicht genau, wo ich dafür suchen müsste, weil ich nicht genau weiß, wie ".class" funktioniert (das Lesen in java.lang.Class hilft mir da auch nicht so recht, weil ich wohl einfach noch Wissenslücken habe, was einiger Inhalt davon bedeutet).
 
Zuletzt bearbeitet von einem Moderator:

Joose

Top Contributor
GetResourceAsStream ist zu finden in java.lang.Class mit folgendem Code:
...
Ich sehe nicht, dass die Methode vorsieht, null zu liefern.
Heißt aber nicht das die Methode es nicht zurückliefern kann. Es gibt in der Methode 2 "returns" wo jeweils wieder eine Methode aufgerufen wird ;)
Aber anstatt dir den Source anzuschauen baue doch einfach eine null-Abfrage in deinen Code ein um das zu überprüfen.

Also vor lookAndFeel.load(SepaRechner3.class.getResourceAsStream(laf.getPath()), SepaRechner3.class);
ein if(SepaRechner3.class.getResourceAsStream(laf.getPath()) != null)
Im if-Zweig eben das LaF laden und im else-Zweig zum Beispiel eine Exception werfen oder sonstiges.

Ich hatte ja bisher in meiner Unwissenheit eher die Vermutung, dass SepaRechner3.class aus irgendeinem Grund nicht funktioniert, aber ich weiß momentan nicht genau, wo ich dafür suchen müsste, weil ich nicht genau weiß, wie ".class" funktioniert (das Lesen in java.lang.Class hilft mir da auch nicht so recht, weil ich wohl einfach noch Wissenslücken habe, was einiger Inhalt davon bedeutet).
".class" gibt dir einfach die Klassendefinition zurück, würde mich wundern wenn diese null wäre ;)
 

ThommiR

Mitglied
Heißt aber nicht das die Methode es nicht zurückliefern kann. Es gibt in der Methode 2 "returns" wo jeweils wieder eine Methode aufgerufen wird ;)
Aber anstatt dir den Source anzuschauen baue doch einfach eine null-Abfrage in deinen Code ein um das zu überprüfen.

Also vor lookAndFeel.load(SepaRechner3.class.getResourceAsStream(laf.getPath()), SepaRechner3.class);
ein if(SepaRechner3.class.getResourceAsStream(laf.getPath()) != null)
Im if-Zweig eben das LaF laden und im else-Zweig zum Beispiel eine Exception werfen oder sonstiges.
Ja, das ist wohl die Quelle. Müsste man manchmal eher auf die Idee kommen, so einfach gegenzuprüfen...
Ich bin jetzt vielleicht noch ein bisschen näher an der Lösung. Aus einem flüchtigen Gedanken heraus habe ich mal die Pfadangabe überprüft. Ich hatte diese aus der Adresszeile des Explorers kopiert, wo die Ordnerstrukturen durch "\" getrennt werden (im String hatte ich es natürlich als "\\" angegeben). Offenbar kommt es doch besser, den Slash zu nutzen, statt den Backslash (ich hatte gelesen, dass die Wahl des Separators Plattformabhängig ist und die Angabe deshalb aus dem Explorer übernommen). Ich schätze, das ist jetzt eine etwas nervige Erkenntnis.
Kurzum, die IllegalArgumentException ist weg (leider kein Brett-vorm-Kopf-Smiley da). Jetzt wundert mich noch, dass der vorherige Test trotzdem noch ausgibt, dass
SepaRechner3.class.getResourceAsStream(laf.getPath()) == null
ist...
Vielleicht sollten wir mal grundlegend meine Pfadangabe prüfen? Ich habe wie folgt als absolute Pfandangabe definieren wollen:

File laf= new File("C:/Eigene Programme/Eclipse/workspace/IbanRechner/src/iban/synthDemo.xml");

Wie falsch ist diese Formulierung? Ich habe vor allem den ganzen Pfad nutzen wollen, weil ich bei einer relativen Angabe nicht sicher war, an welcher Stelle der Quellordner ansetzt. Zählt dafür der "src"-Ordner oder das untergeordnete Projekt?
So schnell läuft es doch wieder auf so grundlegende Fragen hinaus...

".class" gibt dir einfach die Klassendefinition zurück, würde mich wundern wenn diese null wäre ;)
Auch wieder zu kompliziert gedacht, ist ja kein Aufruf einer Methode, sondern eines Attributes. Immer die Grundlagen im Blick behalten...
 

X5-599

Top Contributor
Nach meinem Wissensstand funktioniert der class.getResourceAsStream() nicht mit absoluten Pfadangaben. Zumindest nicht in dem Sinne "C:/Verzeichnis/UnterVerzeichnis...". Eine Resource wird per Namen angesprochen und relativ oder absolut addressiert:
MeineKlasse.class.getResourceAsStream("DieResource.xml"); //relativ: Datei liegt neben MeineKlasse (Selbes Verzeichnis oder besser gesagt: selbes Package)
MeineKlasse.class.getResourceAsStream("anderes/unterpackage/DieResource.xml"); //ebenfalls relativ. Datei liegt hier: erste/zweite/meineklassepackage/anderes/unterpackage.
MeineKlasse.class.getResourceAsStream("/ganz/wo/anders/DieResource.xml"); //absolut: Datei liegt im angegebenen Package. Angefangen beim Root Package.

Frage in die Runde: habe ich in meiner Erklärung was vergessen? Oder könnte man es etwas besser schreiben?

Lange Rede kurzer Sinn: Du müsstest statt: SepaRechner3.class.getResourceAsStream(laf.getPath()) einfach: SepaRechner3.class.getResourceAsStream("synthDemo.xml") schreiben.
 

ThommiR

Mitglied
Danke für die Hinweise. Das werde ich wohl erst morgen testen können, dann gebe ich nochmal Bescheid.

Kleine Frage zwischendurch: hat denn jemand hier auch Erfahrung mit dem SynthLookAndFeel ohne Einlesen einer XML-Datei?
 

ThommiR

Mitglied
Lange Rede kurzer Sinn: Du müsstest statt: SepaRechner3.class.getResourceAsStream(laf.getPath()) einfach: SepaRechner3.class.getResourceAsStream("synthDemo.xml") schreiben.
Das funktioniert offenbar, vielen Dank nochmal!
Kurze Frage noch zu der Erläuterung: Das "Root Package" meint dann vermutlich den "Workspace"-Ordner (zumindest in Eclipse, heißt ja in anderen Programmen teilweise anders) in dem alle Projekte gespeichert sind?

Dann mache ich mich mal daran, zu recherchieren, wie ich die XML-Datei mit den richtigen Informationen befülle....
 

ThommiR

Mitglied
*hmpf* Zu früh gefreut...
Nachdem der Laf jetzt ohne Fehlermeldung aus der Datei eingelesen wurde, wollte ich diesen mit
UIManager.setLookAndFeel(lookAndFeel);
einlesen. Die Folge:

Code:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
 at sun.awt.SunToolkit.getImageFromHash(Unknown Source)
 at sun.awt.SunToolkit.getImage(Unknown Source)
 at javax.swing.ImageIcon.<init>(Unknown Source)
 at javax.swing.plaf.synth.ImagePainter.getImage(Unknown Source)
 at javax.swing.plaf.synth.ImagePainter.paint(Unknown Source)
 at javax.swing.plaf.synth.ImagePainter.paintTextFieldBorder(Unknown Source)
 at javax.swing.plaf.synth.ParsedSynthStyle$DelegatingPainter.paintTextFieldBorder(Unknown Source)
 at javax.swing.plaf.synth.SynthTextFieldUI.paintBorder(Unknown Source)
 at javax.swing.plaf.synth.SynthBorder.paintBorder(Unknown Source)
 at javax.swing.JComponent.paintBorder(Unknown Source)
 at javax.swing.JComponent.paint(Unknown Source)
 at javax.swing.JComponent.paintChildren(Unknown Source)
 at javax.swing.JComponent.paint(Unknown Source)
 at javax.swing.JComponent.paintChildren(Unknown Source)
 at javax.swing.JComponent.paint(Unknown Source)
 at javax.swing.JLayeredPane.paint(Unknown Source)
 at javax.swing.JComponent.paintChildren(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.RepaintManager.paint(Unknown Source)
 at javax.swing.JComponent.paint(Unknown Source)
 at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source)
 at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source)
 at sun.awt.SunGraphicsCallback.runComponents(Unknown Source)
 at java.awt.Container.paint(Unknown Source)
 at java.awt.Window.paint(Unknown Source)
 at javax.swing.RepaintManager$4.run(Unknown Source)
 at javax.swing.RepaintManager$4.run(Unknown Source)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
 at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
 at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
 at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
 at javax.swing.RepaintManager.access$1200(Unknown Source)
 at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
 at java.awt.event.InvocationEvent.dispatch(Unknown Source)
 at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
 at java.awt.EventQueue.access$500(Unknown Source)
 at java.awt.EventQueue$3.run(Unknown Source)
 at java.awt.EventQueue$3.run(Unknown Source)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(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)

Und dieser StackTrace wird im Laufe der Runtime immer wieder ausgeworfen. Irgendwo muss da wohl eine Schleife drin stecken...
Ich suche nach der Fehlerquelle, falls jemand schneller eine Idee hat, bin ich für Hinweise dankbar.
 
Zuletzt bearbeitet von einem Moderator:

X5-599

Top Contributor
Um ehrlich zu sein habe ich Root Package geschrieben weil ich mir nicht sicher bin wie es tatsächlich heisst. Ich nutze Eclipse und hab es gerade nochmal getestet. Mit getResourceAsStream("/meine.xml") findet er die Datei wenn sie im src/ Verzeichnis liegt. Aber auch wenn ich sie ins Projekt Verzeichnis kopiere. Eclipse schaut wohl an beiden Stellen für diese absolute Addressierung.
Wenn man sein Programm als *.jar exportiert (xml Datei muss mit exportiert werden), wird die xml Datei jeweils in die Oberste Ebene gepackt. Also: meineJar.jar/meine.xml
Andere Klassen sind z.B. so reingepackt:
meineJar.jar/KlasseImDefaultPackageVonEclipse.class
meineJar.jar/erstes/unter/paket/EineKlasse.class

KlasseImDefaultPackageVonEclipse.class liegt in keinem Verzeichnis, weil das Default Package von Eclipse halt keines bekommt.
erstes, zweites und unter sind Packages, die beim exportieren zu Verzeichnissen im *.jar werden.
Würde die xml Datei in einem dieser Packages liegen, würde sie auch nach dem exportieren neben den *.class Dateien in diesen Verzeichnissen sein.

Meine Ausdrucksweise oder Bezeichnungen mögen jetzt nicht ganz akkurat sein, aber so reime ich mir persönlich diesen Sachverhalt zusammen. Diese Schreibweise z.B.
"meineJar.jar/erstes/unter/paket/..." ist natürlich keine Verzeichnisstruktur auf der Festplatte. Das soll die Verzeichnis Hierarchie der exportierten jar Datei darstellen, wenn man sie entpackt.

Zu deinem neuen Problem. Ich nehme an es ist dasselbe wie mit der *.xml Datei. Eine Image Resource wird wohl nicht gefunden. Überprüfe mal wo sich das Bild befindet und wie es im Code geladen wird.

EDIT: Ich sehe gerade, der StackTrace geht vom Synth aus los. Eventuell ist die Angabe des zu ladenen Bildes in der *.xml und nicht im Code.
 

ThommiR

Mitglied
Danke für die Hinweise. Ich bin zwar noch nicht so weit, (erstmals) eine jar-Datei daraus zu machen, aber das werde ich mir im Hinterkopf behalten.

Das mit dem Image fiel mir natürlich auch auf und irritierte mich, weil ich kein Bild eingebaut habe. Manchmal hängt man sich an einem Punkt auf und schaut nicht weiter. Jetzt ist mir aufgefallen, dass der Fehler zwei Zeilen weiter vom Image über eine paint-Methode zu folgendem übergeht:
at javax.swing.plaf.synth.ImagePainter.paintTextFieldBorder(Unknown Source)

Es scheint demnach fast mit dem TextField zu tun zu haben. Tatsächlich ist in der XML-Datei (der Großteil des relevanten Codes ist übrigens aus den Beispielprogrammen zum SynthLookAndFeel, die über die Dokumentation angeworben werden) bei den Styles für das TextField ein ImagePainter angegeben, wie ich jetzt festgestellt habe.
Der folgende Abschnitt taucht dazu auf:
<style id="textfield"> <insets top="4" left="6" bottom="4" right="6"/> <state> <font name="Verdana" size="14"/> <color value="#D2DFF2" type="BACKGROUND"/> <color value="#000000" type="TEXT_FOREGROUND"/> </state> <imagePainter method="textFieldBorder" path="images/textfield.png" sourceInsets="4 6 4 6" paintCenter="false"/> </style> <bind style="textfield" type="region" key="TextField"/>

Ich bin jetzt etwas irritiert, warum das TextField eine Bilddatei braucht und wo ich die Datei herbekomme, aber ich bin mal zuversichtlich, dass ich das noch rausfinde und dann schauen wir mal, ob es damit funktioniert.
 

ThommiR

Mitglied
Also im Netz suche ich wahrscheinlich nicht richtig. Auf dem Rechner habe ich ein paar Dateien mit der Bezeichnung "button.png" gefunden, größtenteils in unterschiedlichen Programmordnern, aber keine "textfield.png". Wenn die Komponenten (auch die unveränderten) irgendwie auf einer Bilddatei aufgebaut sind, dann sind diese weder in den Java- noch in den Eclipse-Dateien und auch nicht in den Windows-Ordnern auffindbar (eventuelle versteckte Dateien nicht einbezogen).

Meint ihr, es würde etwas bringen, den Teil mit dem ImagePainter einfach aus der XML-Datei zu entfernen, in der Hoffnung, dass dann auf Standardwerte zurückgegriffen wird und man sich nicht darum kümmern muss, wo die herkommen?
 

ThommiR

Mitglied
Kleines Update:
Es hilft weder, die Komponente mit dem ImagePainter aus der XML-Datei zu entfernen (gleiche Fehlermeldung), noch den ganzen Style für das TextField (offenbar ersetzt der backingStyle diesen Teil nicht, sodass vom Programm dann bemängelt wird, dass der Style für das TextField nicht definiert ist).
Es genügt auch nicht, irgendeine png-Datei zur Verfügung zu stellen (oder der Bezug im Pfad ist wieder falsch, aber eine beliebige Datei würde ja auch sonst vermutlich wenig zielführend sein).
Darüber hinaus überlege ich jetzt, ob ich wirklich das Bild verantwortlich machen kann, in der Komponente ImagePainter sind noch andere Sachen angegeben (Bezug auf die Methode paintTextFieldBorder im StackTrace), die damit zu tun haben könnten. Vielleicht habe ich mich schon wieder zu sehr auf mögliche Ursachen gestürzt, statt erst zu prüfen, ob es wirklich daran liegen kann.
Dann werde ich den Teil mal nachholen...
 

ThommiR

Mitglied
Hm, wenn ich das jetzt richtig verstehe, wird die Angabe "path" als Instanz der Klasse "URL" verwendet. Aus der Beschreibung der Class URL geht hervor, dass eine Pfadangabe der Form "images/textfield.png als relative URL verwendet wird, die sich auf eine andere Ressource bezieht. Im Beispiel ist dafür die URL [URL]http://java.sun.com/index.html[/URL] angeführt, aber wenn ich das richtig verstehe, wird diese Komponente getrennt initialisiert und ist nur in dem Beispiel so genannt.

Das alles scheint Sinn zu ergeben, zumindest in dem Zusammenhang, dass es den StackTrace schon von dem Punkt an erklärt, in dem ImagePainter die Bilddatei zu laden versucht (at javax.swing.ImageIcon.<init>(Unknown Source)), was natürlich nicht geht, wenn der Path nicht funktioniert.
Um nun mehr darüber herauszufinden, auf welche Ressource sich der relative Pfad bezieht, muss ich nochmal schauen, an welcher Stelle path initialisiert wird, denn ImagePainter bekommt den Wert nur übergeben.
Ich vermute, dass auch die Zeilen des StackTraces
at sun.awt.SunToolkit.getImageFromHash(Unknown Source) at sun.awt.SunToolkit.getImage(Unknown Source)
weiteren Aufschluss zu dem relativen Bezug geben, aber ich habe leider keine Ahnung, wo ich die Dateien dazu finde, um genauer zu recherchieren. Sind das Online-Komponenten oder sollte ich die irgendwo auf meinem Rechner finden?
 

ThommiR

Mitglied
Vermutlich letzte Ergänzung für heute:
Ich bin den Verweisen von der Methode getImage(URL url) der Klasse ImageIcon bis zur gleichnamigen Methode der Klasse Toolkit gefolgt. Die Methode wird aufgerufen durch den Konstruktor
public ImageIcon(URL location, String description) { image = Toolkit.getDefaultToolkit().getImage(location); if (image == null) { return; } this.location = location; this.description = description; loadImage(image); }
Die Klasse Toolkit scheint aber nun ein Interface zu sein, die dortige Methode getImage(URL url) ist als abstrakte Methode angelegt. Wo suche ich nach dem Code, in dem das Interface implementiert und die Methode genauer definiert ist?
Da wir uns damit wieder mehr in grundlegenden Kenntnissen bewegen (ich kann ja immer mehr verstehen, dass mit dem SynthLookAndFeel scheinbar noch nicht viele Erfahrungswerte hier im Forum vorliegen), habe ich Hoffnung, dass mir damit jemand helfen kann.
 

ThommiR

Mitglied
Vermutlich letzte Ergänzung für heute:
Ich bin den Verweisen von der Methode getImage(URL url) der Klasse ImageIcon bis zur gleichnamigen Methode der Klasse Toolkit gefolgt. Die Methode wird aufgerufen durch den Konstruktor
public ImageIcon(URL location, String description) { image = Toolkit.getDefaultToolkit().getImage(location); if (image == null) { return; } this.location = location; this.description = description; loadImage(image); }
Die Klasse Toolkit scheint aber nun ein Interface zu sein, die dortige Methode getImage(URL url) ist als abstrakte Methode angelegt. Wo suche ich nach dem Code, in dem das Interface implementiert und die Methode genauer definiert ist?
Da wir uns damit wieder mehr in grundlegenden Kenntnissen bewegen (ich kann ja immer mehr verstehen, dass mit dem SynthLookAndFeel scheinbar noch nicht viele Erfahrungswerte hier im Forum vorliegen), habe ich Hoffnung, dass mir damit jemand helfen kann.
 

X5-599

Top Contributor
Also: Wenn das textfield.png nicht geladen werden kann, wird es sich vermutlich an falscher Stelle befinden. Ich weiss du hast kein textfield Bild, aber es würde theoretisch jedes *.png Bild funktionieren (sieht dann natürlich unter Umständen weniger gut aus). Dazu wo man die Bilder her bekommt. Aus dem offiziellen Beispiel (auf das du dich glaube ich auch beziehst) gibt es einen Verweis auf ein *.zip Archiv mit dem gesamten Projekt. Da sind dann auch die Bilder drin. Zu finden hier:
https://docs.oracle.com/javase/tutorial/uiswing/examples/lookandfeel/index.html#SynthDialog
Im "Table of Examples" ist es das dritte Projekt: Synth Dialog Project. Die ZIP Datei heisst: lookandfeel-SynthDialogProject.zip
 

ThommiR

Mitglied
Okay, vielen Dank für den Augenöffner. Das war wieder so eine clevere Aktion: Ich hatte mir nur die Programmdatei dort gezogen, nicht das zip-Archiv. Später hatte ich dann nicht mehr im Sinn, dass da noch mehr Dateien sein könnten.
Trotzdem musste ich in Eclipse noch den Ordner "refreshen", damit es richtig geladen hat, aber jetzt läuft das Programm erst mal ohne Murren und ich kann mich tatsächlich damit beschäftigen, wie ich das LaF nach meinen Wünschen anpasse (und was beim Zeichnen eigener Buttons etc. zu beachten ist).

Wenn es dazu Fragen geben wird, werde ich vermutlich einen neuen Thread dazu erstellen. Vielleicht hilft dieser ja trotzdem dem ein oder anderen, meine Fehler nicht zu wiederholen.

Vielen Dank nochmal für alle Hinweise!!!
 

Neue Themen


Oben