0

I have problem with change element FXML from another class.

My project:

  1. MainClass.java
  2. Tools.java (second class)
  3. MainFxmlController.java (controller)
  4. TEMPLATE.fxml (template ScneeBuilder)

I need in method Tools.java excecute setText on my button from MainFxmlController. Please Help.

MainClass.java

package my.project.service.tools;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.io.IOException;

public class MainClass extends Application {

    public static FXMLLoader loader;
    public static MainFxmlController controller;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) throws IOException {
        loader = new FXMLLoader();
        loader.setLocation(this.getClass().getResource("/TEMPLATE.fxml"));
        VBox mainView = loader.load();

        controller = loader.getController();

        Scene scena = new Scene(mainView);
        stage.setScene(scena);
        stage.show();
    }
    
    
    public MainFxmlController getController(){
        return controller;
    }
}

MainFxmlController.java

package my.project.service.tools;

import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;


public class MainFxmlController {

    @FXML public Button button1;
    @FXML public TextArea text1;

    public MainFxmlController(){
    }

    @FXML
    void initialize(){
    }

    public void pressButton(){
        Tools tools = new Tools();
        tools.toolsMethod("HAHAHHAA");
    }

    public void setTextArea(String txt){
        text1.setText(txt);
    }
}

Tools.java

package my.project.service.tools;

public class Tools {

    public void toolsMethod(String txt){
        MainClass main = new MainClass();
        MainFxmlController controller = main.getController();
        controller.setTextArea("HAHAHA");
    }
}

TEMPLATE.fmlx

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>

<VBox prefHeight="400.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="my.project.service.tools.MainFxmlController">
  <children>
    <AnchorPane maxHeight="-1.0" maxWidth="-1.0" prefHeight="-1.0" prefWidth="-1.0" VBox.vgrow="ALWAYS">
      <children>
            <Button fx:id="button1" layoutX="47.0" layoutY="81.0" mnemonicParsing="false" onAction="#pressButton" prefHeight="50.0" prefWidth="85.0" text="Button" />
            <TextArea fx:id="text1" layoutX="154.0" layoutY="14.0" prefHeight="200.0" prefWidth="468.0" />
      </children>
    </AnchorPane>
  </children>
</VBox>

Error:

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:8865)
    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:3876)
    at javafx.graphics/javafx.scene.Scene$MouseHandler.access$1300(Scene.java:3604)
    at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1874)
    at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2613)
    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:395)
    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:175)
    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:275)
    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 my.project.service.tools.MainFxmlController.setTextArea(MainFxmlController.java:26)
    at my.project.service.tools.Tools.toolsMethod(Tools.java:6)
    at my.project.service.tools.MainFxmlController.pressButton(MainFxmlController.java:22)
    ... 58 more
mAsHER
  • 33
  • 7
  • 2
    You can't create a random instance of your controller and expect it to have references to the objects showing on screen. You need to get the controller from the `FXMLLoader` and use that instance. – Slaw Oct 21 '20 at 08:18
  • can you explain how? Need to add something like this to Tools.java? https://ibb.co/GcF9Pwc – mAsHER Oct 21 '20 at 09:16
  • 1
    See [Passing Parameters JavaFX FXML](https://stackoverflow.com/questions/14187963/passing-parameters-javafx-fxml). And remember, it's important you use the correct controller _instance_. – Slaw Oct 21 '20 at 09:24
  • @Slaw pretty sure we have tons of duplicates (this problem appears every other day at least) .. but can't seem to be able to find something appropriate. Or is this sooo basic that it's more like a typo (which is the case as well, as the answer points out)? – kleopatra Oct 21 '20 at 09:48
  • 1
    no external references (and no screenshots of text anywhere) - instead edit your question with any clarifications/variants that you tried. Rephrasing @Slaw comment: you must __load__ the fxml to get a controller properly setup, only after doing so you can use any of the custom methods of that __instance__ of the controller (vs. instantiating another instance via its constructor). Looks like you should work through a tutorial on fxml to understand how it works .. – kleopatra Oct 21 '20 at 09:53
  • Thanks, I made changes to the Tools.java - the NullPointer error is gone but I can't see any changes on the form. – mAsHER Oct 21 '20 at 10:11
  • 1
    You're on the right track but you're still using the wrong instance. Each time you load an FXML file with `FXMLLoader` a **new** view+controller pair is created. Your edit now properly loads a controller but it's not the one associated with the view on screen. You need to find a way to reference the _existing_ controller instance. That means passing the instance around as needed. When you're ready for it, a more robust solution would be to create a proper MVC (or similar) architecture and pass the model around (updating the model would notify the controller/view). – Slaw Oct 21 '20 at 10:15
  • @kleopatra I think the problem is this question has been asked-and-answered many times, but often only for the questioner's exact scenario making it hard to find a Q&A that's broadly relatable (i.e. a proper duplicate). And unfortunately a canonical Q&A has never appeared for this problem (at least not one that I'm aware of). We typically direct the people who ask this question to _Passing Parameters JavaFX FXML_, but even that Q&A seems to go too far beyond the scope of "Why is my field null?" to be a good duplicate. – Slaw Oct 21 '20 at 10:18
  • It Works! Update my code. 1. MainClass.java: Add static variable MainFxmlController and getter getController. 2. Tools.java getController and setText on him. – mAsHER Oct 21 '20 at 10:41
  • no, don't use static scope for anything .. instead pass parameters around as suggested in the QA referenced by @Slaw – kleopatra Oct 21 '20 at 10:44
  • @Slaw thanks for the info .. maybe some kind soul has enough leisure time to come up with a canonical answer :) – kleopatra Oct 21 '20 at 10:45
  • 2
    @kleopatra I'd do it but I'm still waiting for the time (and motivation) to follow through with my plan to make a canonical Q&A for all the `IllegalAccessError`s you can get with JavaFX now that modules exist lol – Slaw Oct 21 '20 at 10:48

1 Answers1

0

Your text area is called text1 in the FXML file and textArea1 in the Java controller. When you call textArea1.setText(txt);, Java returns the FXML occurrence of textArea1 which doesn't exist, so it returns null.

0009laH
  • 1,735
  • 11
  • 24