1

I have the code below which contains a class and a nested JavaFX Controller.I initialize the JavaFX Controller class and i get an instance of it like you can see.

SpeechWindow class:

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;

import application.Main;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

/**
 * SpeechWindow
 *
 */
public class SpeechWindow extends Stage {

    private Container container = new Container();

    /**
     * Constructor
     */
    public SpeechWindow() {

        setTitle("SpeechResults");
        setScene(new Scene(container));
    }

    /**
     * @param text
     */
    public void appendText(String text) {
        container.appendText(text);
    }

    /**
     * 
     */
    public void clear() {
        container.clear();
    }

    public class Container extends BorderPane implements Initializable {

        @FXML
        private TextArea textArea;

        public Container() {
            // FXMLLOADER
            FXMLLoader loader = new FXMLLoader(getClass().getResource("SpeechWindow.fxml"));
            try {
                loader.load();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        @Override
        public void initialize(URL location , ResourceBundle resources) {
            System.out.println("Container has been initialized..");
        }

        public void appendText(String text) {
            Platform.runLater(() -> textArea.appendText(text + "\n"));
        }

        public void clear() {
            Platform.runLater(textArea::clear);
        }

    }

}

Here it is the FXML code:

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

<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.BorderPane?>


<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1">
   <center>
      <TextArea fx:id="textArea" editable="false" prefHeight="200.0" prefWidth="200.0" promptText="...no response" wrapText="true" BorderPane.alignment="CENTER" />
   </center>
</BorderPane>

Try to call it from the Main JavaFX Application class creating an instance of SpeechWindow and call appendText(); method.A null pointer comes out why?

The goal is:

Then i want to create an instance the outer class and use it.


What goes wrong:

If i create an instance of SpeechWindow class and call the method appendText(); i get null pointer exception...Why that happens,i see everything done fine.What is my mistake?

2 Answers 2

2

You never connect the controller instance to the fxml.

Use setController for the FXMLLoader to set the controller class.

Furthermore you need to add the result of loading the fxml to the scene somehow. Probably you should replace the root element of the fxml with a fx:root element.

BTW: It seems like a bad idea to simply catch a load an exception, if the instance cannot be used, if such a exception happens...

public Container() {
    // FXMLLOADER
    FXMLLoader loader = new FXMLLoader(getClass().getResource("SpeechWindow.fxml"));

    // set controller & root
    loader.setController(this);
    loader.setRoot(this);
    try {
        loader.load();
    } catch (IOException ex) {
        // throw as cause of RuntimeException
        throw new IllegalStateException(ex);
    }
}
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.BorderPane?>

<fx:root type="javafx.scene.layout.BorderPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1">
   <center>
      <TextArea fx:id="textArea" editable="false" prefHeight="200.0" prefWidth="200.0" promptText="...no response" wrapText="true" BorderPane.alignment="CENTER" />
   </center>
</fx:root>
Sign up to request clarification or add additional context in comments.

1 Comment

Oh daaaamn how i missed that ,thanks Fabian ! I will check if it works and then mark it as answer...
1

You must use FXMLLoader.getController() method to obtain your Container class before calling its methods.

Try to call

FXMLLoader loader = new FXMLLoader(getClass().getResource(".../SpeechWindow.fxml"));

from SpeechWindow class instead of Container's constructor. Then retreive the Container class by

Container container = loader.getController();

2 Comments

Thanks for the effort Cryptor but here i want to use fx:root,i missed something that you can see in Fabian's answer.
Anyway this answer shouldn't work since there is no controller created by the FXMLLoader, since there is not fx:controller attribute specified in the fxml...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.