2016-06-21 13 views
0

Ich schreibe ein einfaches Programm, das aus einem Fenster mit 8 Tasten mit verschiedenen Farben besteht, die zu einer VBox hinzugefügt wurden und dann zur Szene der Programmbühne hinzugefügt werden.NullPointerException bei Verwendung eines hexadezimalen Werts als Parameter einer Methode

für eine Schaltfläche die Farbe zu ändern, ich habe die setRippleColor() Methode aufzurufen, deren Definition ist die folgende:

public void setRippleColor(Color color) { 
     ((Shape) ((SkinBase) getSkin()).getChildren().get(0)).setFill(color); 
    } 

Das Problem ist, dass, wenn ich diese Methode aufrufen, ein Color Objekt als Parameter verwendet wird, erhalte ich a NullPointerException.

Zum Beispiel, wenn ich diesen Code verwenden:

 buttonGreen.setRippleColor((Color.web("0x259B24"))); 
     buttonOrange.setRippleColor(Color.web("0xe67e22")); 
     buttonBlue.setRippleColor(Color.web("0x3498db")); 
     buttonPurple.setRippleColor(Color.web("0x9b59b6")); 
     buttonYellow.setRippleColor(Color.web("0xf1c40f")); 
     buttonRed.setRippleColor(Color.web("0xe74c3c")); 
     buttonBrown.setRippleColor(Color.web("0x663300")); 
     buttonGrey.setRippleColor(Color.web("0x222222")); 

     VBox verticalLayout = new VBox(8); 
     verticalLayout.getChildren().addAll(buttonGreen, 
              buttonOrange, 
              buttonBlue, 
              buttonPurple, 
              buttonYellow, 
              buttonRed, 
              buttonBrown, 
              buttonGrey); 

die Konsole dies sagen wird:

Exception in Application start method 
java.lang.reflect.InvocationTargetException 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(Unknown Source) 
    at com.sun.javafx.application.LauncherImpl.launchApplication(Unknown Source) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at sun.launcher.LauncherHelper$FXHelper.main(Unknown Source) 
Caused by: java.lang.RuntimeException: Exception in Application start method 
    at com.sun.javafx.application.LauncherImpl.launchApplication1(Unknown Source) 
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(Unknown Source) 
    at java.lang.Thread.run(Unknown Source) 
Caused by: java.lang.NullPointerException 
    at CustomButton.setRippleColor(CustomButton.java:166) 
    at StartingPoint.start(StartingPoint.java:25) 
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(Unknown Source) 
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(Unknown Source) 
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(Unknown Source) 
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source) 
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) 
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(Unknown Source) 

Als die 166. und 25. Codezeilen der Definition des Verfahrens und die erster Aufruf davon jeweils.

Wenn ich jedoch einen Hexadezimalwert als Farbe verwende, verwende ich eine der Standardfarben der Klasse (Color.GREEN, zum Beispiel), alles läuft perfekt.

Es ist wichtig zu erwähnen, dass ich nicht die java.awt.Color Klasse statt javafx.scene.paint.Color verwende; Die Bibliothek ist nicht das Problem.

UPDATE: Ich habe einige rudimentary Protokollierung, um zu wissen, was null ist.

Statt Color.web("...") als Parameter für setRippleColor() verwenden, habe ich ein paar Color Objekte, deren Definition ist das, was ich am Anfang waren die setRippleColor() ‚s-Parameter, und ich umringten die Anrufe an die setRippleMethod() mit folgenden try{} catch{}:

Color green = Color.web("0x259B24"); 

     try { 
      buttonGreen.setRippleColor(green); 
     } catch (NullPointerException exception) { 

      SkinBase skin = (SkinBase) buttonGreen.getSkin(); 
      ObservableList<Node> children = skin.getChildren(); 
      Shape shape = (Shape) skin.getChildren().get(0); 

      System.out.println("Color " + green); 
      System.out.println("Skin: " + skin); 
      System.out.println("Children: " + children); 
      System.out.println("Shape: " + shape); 

     } 

Und das ist, was die Konsole ausgibt:

Exception in Application start method 
java.lang.reflect.InvocationTargetException 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(Unknown Source) 
    at com.sun.javafx.application.LauncherImpl.launchApplication(Unknown Source) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at sun.launcher.LauncherHelper$FXHelper.main(Unknown Source) 
Caused by: java.lang.RuntimeException: Exception in Application start method 
    at com.sun.javafx.application.LauncherImpl.launchApplication1(Unknown Source) 
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(Unknown Source) 
    at java.lang.Thread.run(Unknown Source) 
Caused by: java.lang.NullPointerException 
    at StartingPoint.start(StartingPoint.java:31) 
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(Unknown Source) 
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(Unknown Source) 
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(Unknown Source) 
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source) 
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) 
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(Unknown Source) 

so weit wie ich es verstehe, bedeutet dies, dass die Schaltfläche s Kin's Kinder geben null zurück, aber ich verstehe nicht, warum dies nicht geschieht, wenn ich Color.GREEN anstelle des Objekts verwende, das im obigen Code gefunden wird.

UPDATE 2: Es stellt sich heraus, dass, wenn ich Color.GREEN als Parameter für setRippleColor() verwenden das Ergebnis das gleiche ist, dass wenn ich Color.web("#colorstring") verwenden, was offensichtlich ist und es keine Erklärung wäre, wenn das nicht war der Fall. Ich weiß nicht warum, aber ich habe die Erinnerung, Color.GREEN zu verwenden und das Programm ohne Fehler laufen zu lassen.

Die gute Sache ist, dass ich mich jetzt daran erinnern werde, dass jedes Mal, wenn etwas keinen Sinn ergibt, ich den Code erneut ausführen muss und sicherstellen, dass es für mich keinen Sinn ergibt, weil ich nicht genug habe Wissen über das Thema, und nicht weil es nie passiert ist.

Also, das Problem lag daran, dass die Haut der Schaltfläche nicht initialisiert wurde, bevor die setRippleColor()-Methode aufgerufen wird.

Dies ist, wie ich es gelöst:

hat
try{ 
((Shape) ((SkinBase) getSkin()).getChildren().get(0)).setFill(color); 
} catch (NullPointerException exception){ 
    createDefaultSkin(); 
    setRippleColor(color); 
} 

Wenn die Haut nicht initialisiert wurde, wenn die Methode aufgerufen wird, wird es initialisiert und dann wieder die setRippleColor() nennt sich.

+0

Loggen Sie sich ein, um zu sehen, was null ist. Es ist entweder die Haut, die Kinderliste der Haut (unwahrscheinlich) oder das erste Kind der Haut (ziemlich unwahrscheinlich). Vielleicht nennst du das irgendwie bevor die Haut initialisiert wird? –

+2

Selbst wenn Sie es schaffen, es zu arbeiten, ist dies ein ziemlich zerbrechliches Design. Die Skin-Implementierungen für Dinge wie Buttons in JavaFX 8 sind nicht Teil der öffentlichen API und könnten (und werden wahrscheinlich) für spätere Java-Versionen in einer binär inkompatiblen Weise geändert werden. Ich denke, du solltest überdenken, was du zu tun versuchst und mit welchen Mitteln du es erreichen willst. Ich weiß nicht genau, was Sie zu tun versuchen, aber normalerweise können Sie CSS verwenden, um Farben auf Schaltflächen zu setzen (zB 'button.setStyle (" - fx-base: palegreen; ");') – jewelsea

+0

Ich denke, in Licht von deinem Kommentar, dass "Color.GREEN" funktioniert, überprüfe auch, dass 'Color.web (...)' nicht null zurückgibt, obwohl ich es kaum glauben kann. –

Antwort

1

Die wahrscheinlichste Ursache ist, dass Sie versuchen, diese Methoden aufzurufen, bevor die Skin initialisiert wurde. In diesem Szenario gibt getSkin()null zurück, und ((SkinBase)getSkin()).getChildren() wird daher eine Nullzeigerausnahme auslösen.

Ein einfacher Weg, dies zu vermeiden, ist eine NULL-Prüfung zu tun:

public void setRippleColor(Color color) { 
    if (getSkin() == null) { 
     createDefaultSkin(); 
    } 
    SkinBase skin = (SkinBase) getSkin(); 
    Shape shape = (Shape) skin.getChildren().get(0); 
    shape.setFill(color); 
} 

Sie können auf diesem Code wahrscheinlich erheblich verbessern: es scheint, dass Sie wirklich irgendwo im Code sollen wissen, was das erste Kind der Haut ist und sollte in der Lage sein, direkt darauf zu verweisen. Dies wird jedoch zumindest eine Lösung bieten.