NullPointerException problem z instancją controllera JavaFx

0

WItam mam problem wywala mi wyjątek NullPointerException. Utworzyłem nową klasę i tam chce instancję controllera zrobić aby mieć dostęp do pól controlek i na nich działać. (tak wiem klasy z wielkiej litery juz poprawiłem).

Gościu na stackoverflow mi coś takiego odpisał:

The controller instance you try to retrieve the value from is not used with an fxml. None of the nodes are injected. Even if you load the corresponding fxml in the setDate method, you'd retrieve the value from a control that was never displayed...

package com.controller;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;

import java.net.URL;
import java.time.LocalDate;
import java.util.Date;
import java.util.ResourceBundle;

public class addChangeController implements Initializable {

    @FXML
    private Button addChangeButton;



    @FXML
    private DatePicker dateChangePicker;

    public void setDateChangePicker(DatePicker dateChangePicker) {
        this.dateChangePicker = dateChangePicker;
    }
    public DatePicker getDateChangePicker() {
        return dateChangePicker;
    }

    @FXML
    private Label descDatePicker;

    @FXML
    private Label fromHourLabel;

    @FXML
    private Label toHourLabel;

    @FXML
    private Label statusLabel;

    @FXML
    private Spinner<Integer> fromHourSpinner;

    @FXML
    private Spinner<Integer> toHourSpinner;




    SpinnerValueFactory<Integer> spinner1 = new SpinnerValueFactory.IntegerSpinnerValueFactory(1,24,8);
    SpinnerValueFactory<Integer> spinner2 = new SpinnerValueFactory.IntegerSpinnerValueFactory(1,24,8);


    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        fromHourSpinner.setValueFactory(spinner1);
        fromHourSpinner.setEditable(true);
        toHourSpinner.setValueFactory(spinner2);
        toHourSpinner.setEditable(true);
    }


    @FXML
    public void tempDownload(){
        addChangeLogic logic = new addChangeLogic();
        logic.setDate();

    }
}
package com.controller;

import java.time.LocalDate;

public class addChangeLogic {



    public void setDate (){
        addChangeController add = new addChangeController();
         LocalDate date = add.getDateChangePicker().getValue();
        System.out.println(date.toString());
    }
}
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1787)
    at javafx.fxml/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1670)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at 
javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
    at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
    at javafx.graphics/javafx.scene.Node.fireEvent(Node.java:8879)
    at javafx.controls/javafx.scene.control.Button.fire(Button.java:200)
    at javafx.controls/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:206)
    at javafx.controls/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
    at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Scene.java:3851)
    at javafx.graphics/javafx.scene.Scene$MouseHandler.access$1200(Scene.java:3579)
    at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1849)
    at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2588)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:397)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:434)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:390)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:433)
    at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:556)
    at javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:942)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:76)
    at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at javafx.base/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:273)
    at javafx.fxml/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:83)
    at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1784)
    ... 47 more
Caused by: java.lang.NullPointerException
    at ProjectCPApril/com.controller.addChangeLogic.setDate(addChangeLogic.java:11)
    at ProjectCPApril/com.controller.addChangeController.tempDownload(addChangeController.java:66)
    ... 58 more
Stop
0

Na wstępie:

  • nazwy komponentów Java zaczynamy z wielkiej litery (nazwy klas, interfejsów, typów wyliczalnych itp.)
  • w klasach najpierw definiujemy pola, później metody - nie przeplatamy ich między sobą.
    Polecam zerknąć do np. Google Java Style Guide.
public class addChangeLogic {

    public void setDate (){
        addChangeController add = new addChangeController();  // tutaj tworzysz sobie nową instancję kontrolera, który nie jest powiązany z widokiem FXML i nie został zarejestrowany jako kontroler JavaFX
         LocalDate date = add.getDateChangePicker().getValue();
        System.out.println(date.toString());
    }
}

Konkretne instancje Twoich klas addChangeController i addChangeLogic nie są ze sobą powiązane w momencie wywołania metody setDate(), tak jak byś to sobie wyobrażał.

To można porównać do mniej więcej poniższego przykładu.

public class Driver {
  private String name;
  
  public Driver(String name) {
    this.name = name;
  }
  
  public void drive(){
    Car car = new Car("Dacia","Duster");
    System.out.println(String.format("Driver \"%s\" is driving the following car: \"%s\" - \"%s\".", name, car.getMake(), car.getModel()));
  }
}

public class Car {
  private String make;
  private String model;
  public Car(String make, String model) {
    this.make = make;
    this.model = model;
  }

  public String getMake() {
    return make;
  }

  public String getModel() {
    return model;
  }
}

public class Main {
  public static void main(String... args) {
    Car car = new Car("Audi","A6");
    Driver driver = new Driver("Audi driver");
    driver.drive();
  }
}
Driver "Audi driver" is driving the following car: "Dacia" - "Duster".
0

Dzięki oczywiście zrozumiałem to jak najbardziej. Chciałem tworzyć instancję pół które w tym momencie były nullami. Wystarczyło w funkcjach w klasie *logic przesłać jako argument obiekt klasy *controller. No i w klasie *controller wywoływać metody z argumentem (this). Dzięki wielkie, kod też poprawiłem żeby wyglądał po ludzku.

1 użytkowników online, w tym zalogowanych: 0, gości: 1