0

I have two fxml files, and each fxml files has a controller. In the first fxml file i have a "base" anchorpane, and on this a smaller "second" anchorpane. In the second fxml file i have a "third" anchorpane that is as big as the "second" anchorpane in the first fxml. On this "third" anchorpane i have a TableView, that is a little smaller, than the "third" anchorpane. In the first controller i set the content of "second" anchorpane to the second fxml file with FXMLLoader. In first controller i have a method, that set the background color of "second" anchorpane to yellow, and call a method from the second controller. This method (in the second controller) wants to make the TableView bigger, but i got error messages. What's wrong with it?

The first controller:

public class Controller implements Initializable {

@FXML
AnchorPane baseanc;
@FXML
AnchorPane ancpane2;
@FXML
Button button;

controller2 contr2 = new controller2();

public void testMethod() {
    ancpane2.setStyle("-fx-background-color: #ffff00");
    contr2.testFunc();
}

public void buttonAction(ActionEvent event) {
    testMethod();
}

@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
    try {
        AnchorPane root = FXMLLoader.load(getClass().getResource("fxml2.fxml"));
        ancpane2.getChildren().setAll(root);
    } catch (IOException e) {
        e.printStackTrace();
    }
}
}

The second controller:

public class controller2{

@FXML
TableView table;

public void testFunc() {
    table.setPrefHeight(720);
} 
}

The first fxml:

<AnchorPane fx:id="baseanc" xmlns="http://javafx.com/javafx/8.0.221" 
    xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
        <children>
          <AnchorPane fx:id="ancpane2" prefHeight="720.0" prefWidth="640.0"/>
          <Button fx:id="button" onAction="#buttonAction" text="Button" />
       </children>
    </AnchorPane>

The second fxml:

  <AnchorPane fx:id="ancpane3" xmlns="http://javafx.com/javafx/8.0.221" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.controller2">
    <children>
     <TableView fx:id="table" prefHeight="600.0" prefWidth="540.0">
      <columns>
       <TableColumn prefWidth="75.0" text="C1" />
       <TableColumn prefWidth="75.0" text="C2" />
      </columns>
    </TableView>
  </children>
</AnchorPane>

The error messages:

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:1782)
    ... 47 more
Caused by: java.lang.NullPointerException
    at sample.controller2.testFunc(controller2.java:13)
    at sample.Controller.testMethod(Controller.java:27)
    at sample.Controller.buttonAction(Controller.java:31)
    ... 58 more
Hunor
  • 53
  • 1
  • 1
  • 6
  • Asside from the fact that you do not use `controller2` with a fxml this question seems pretty much a duplicate of this one: https://stackoverflow.com/questions/14187963/passing-parameters-javafx-fxml – fabian Oct 26 '19 at 22:25
  • I check it. Only this way works? I'm a beginner, and i don't understand that. Can i make it otherwise? – Hunor Oct 27 '19 at 07:41
  • 1
    There are multiple possibilities mentioned in the answers there. Not sure if the list is exhaustive, but creating a new instance of the controller class without telling `FXMLLoader` one way or another to use that instance as controller when loading the fxml just results in an instance that has no connection to the scene created based on the fxml whatsoever (unless you count access by both to the same `static` data (injecting to `static` members doesn't work)). – fabian Oct 27 '19 at 08:12

1 Answers1

1

The Problem is that regular JavaFX Controllers should not be treated as Single Instances (because the are not). Everything Anotatated with @FXML will only INJECT into the Controller, after the FXML is loaded

so your call "new Controller2"

public class controller2{

  @FXML
  TableView table;
  // Will be null without loading of a fxml

  public void testFunc() {
      table.setPrefHeight(720);
  } 
}

Hence the Nullpointer Exception.

after the Initialize, you should inject the initialized Controller, by the FXML Loader.



//Initialize a loader FOR the fxml with the ressource as Constructor parameter
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("fxml2.fxml"));
// then load!
AnchorPane root = fxmlLoader.load();
//Inject the Controller!

controller2= (Controller2) fxmlLoader.getController();
// in that order. 

then the initilialized Controller of the fxml should be the correct instance .

Luxusproblem
  • 1,913
  • 11
  • 23
  • First of all. There is nothing wrong with the second fxml file, just accidentally pasted the same as in the first fxml file. I edited now. BUT!! I corrected what you said, but i got the same errors. :( – Hunor Oct 27 '19 at 06:29
  • @HunorCode Im sorry, I made a mistake. You need to initialize with the constructor of the FXMLLoader for the FXML : **FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("fxml2.fxml"));** and then load(). now you can inject the Controller. I also edited my answer. – Luxusproblem Oct 27 '19 at 09:38
  • Thanks a lot man, my code works (not the example, I showed here), and now i can move on. Thanks! – Hunor Oct 28 '19 at 13:51