GoXR3Plus GoXR3Plus - 1 month ago 23
Java Question

Nested JavaFX Controller inside public class

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?

Answer

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>