4

Im fairly new to both stackoverflow and javafx so please be nice.

Description of what Im doing:

I am making a simple quiz game. First window is just a like a welcome/start screen, when that button is clicked we get to the second screen where all the category buttons are, when one of them is clicked it will randomly pick a question of that kind of category user has selected and the third and last window will appear with the questions category as a label, question as textfield and answear as textfield.

enter image description here

Problem: Whenever a category is clicked I need that current controller to set the next controllers textfields and label. I havent come to far with this. I just get a nullpointerexception when im calling the setQuestion method in the second controller, FXMLCategoriesDocumentController, when I tried to debug it it just says that the instantiated "questControll" is null all the time, and the "questControll.question/category/answear" is referenced from a null object

Code:

second controller

public class FXMLCategoriesDocumentController implements Initializable {

/**
 * Initializes the controller class.
 */
private FXMLQuestionDocumentController questControll;
private Question quest;

@FXML
private void geografButtonAction(ActionEvent event) {
    try {
        FXMLLoader fxmlQuestLoader = new FXMLLoader(getClass().getResource("FXMLQuestionDocument.fxml"));
        this.questControll = fxmlQuestLoader.<FXMLQuestionDocumentController>getController();

        quest = new Question("Geografi", "Vad heter Sveriges huvudstad?", "Stockholm");
        questControll.setQuestion(quest.getCategory(), quest.getQuestion(), quest.getAnswear());
        Parent root1 = (Parent) fxmlQuestLoader.load();
        root1.setId("pane");
        Stage app_stage = (Stage)((Node) event.getSource()).getScene().getWindow();
        Scene root1_scene = new Scene(root1);
        root1_scene.getStylesheets().addAll(this.getClass().getResource("style.css").toExternalForm());
        app_stage.hide();
        app_stage.setScene(root1_scene);
        app_stage.show();

        } catch(Exception e) {
       e.printStackTrace();
      }
}

third controller

public class FXMLQuestionDocumentController implements Initializable {


private FXMLCategoriesDocumentController catControll;
private Question quest;

@FXML
public Label category = new Label();
@FXML
public TextField question = new TextField();
@FXML
public TextField answear = new TextField();
/**
 * Initializes the controller class.
 */
@Override
public void initialize(URL url, ResourceBundle rb) {
}
public void setQuestion(String cat, String quest, String ans){
    if(category.getText() == null || question.getText() == null || answear.getText() == null){
        System.out.println("everything is null");
    }else{
        category.setText(cat);
        question.setText(quest);
        answear.setText(ans);

    }
}

Question class

public class Question {
private String category;
private String question;
private String answear;

public Question(String cat, String quest, String ans){
    this.category = cat;
    this.question = quest;
    this.answear = ans;
}


public void setCategory(String cat){
    this.category = cat;
}
public void setQuestion(String quest){
    this.question = quest;
}
public void setAnswear(String ans){
    this.answear = ans;
}
public String getCategory(){
    return category;
}
public String getQuestion(){
    return question;
}
public String getAnswear(){
    return answear;
}

}

FXML second controller(category) category xml

FXML third controller(question)

question xml

Pateman
  • 53
  • 5

1 Answers1

1

You can specify the the class of controller in each XML-File by using the fx:controller-Tag (here) in the highest element of your (f)xml-Tree.

You can load it then by using this:

YourCustomController controller;
//some code...
try {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("FXMLQuestionDocument.fxml"));
    controller = loader.<YourCustomController>getController();
    //assume that we create a question here
    Question q = new Question(...);
    controller.setQuestion(q);
}
//further code...

Edit after comments:

As fabian said, attributes annotated with @FXML are created before the initialize()-method if the fx:id-tag is set for an element in your FXML-file. The fx:id-tag must be the same as the attribute in your controller.

In you fxml-file (for example a Label):

<Label fx:id="question" ...>
    ....
</Label>

In your Controller-class:

public class YourCustomController implements Initializable {

    @FXML Label question;

    //...
    public void initialize() {
    //...
    }

    public void setQuestion(Question q) {
         question.setText(q.getQuestion();
    }
}

For further information, see the link in jewelseas comment.

I tried this tomorrow and I hope I transferred it here the right way.

Edit from July, 13th

In your FXMLQuestionDocumentController, you don't need to initiliaze your controls. See:

  public class FXMLQuestionDocumentController implements Initializable {

      private FXMLCategoriesDocumentController catControll;
      private Question quest;

      @FXML
      public Label category;
      @FXML
      public TextField question;
      @FXML
      public TextField answear;
}

Also, initialize your controller after you initialized your Pane.

  `@FXML
   private void geografButtonAction(ActionEvent event) {
   try {
       FXMLLoader fxmlQuestLoader = new FXMLLoader(getClass().getResource("FXMLQuestionDocument.fxml"));
       quest = new Question("Geografi", "Vad heter Sveriges huvudstad?", "Stockholm");

       Parent root1 = (Parent) fxmlQuestLoader.load();
       root1.setId("pane");
       this.questControll = fxmlQuestLoader.FXMLQuestionDocumentController>getController();
       questControll.setQuestion(quest.getCategory(), quest.getQuestion(), quest.getAnswear());
       Stage app_stage = (Stage)((Node) event.getSource()).getScene().getWindow();
       Scene root1_scene = new Scene(root1);
       root1_scene.getStylesheets().addAll(this.getClass().getResource("style.css").toExternalForm());
       app_stage.hide();
       app_stage.setScene(root1_scene);
       app_stage.show();

    } catch(Exception e) {
       e.printStackTrace();
  }

}`

Supahupe
  • 515
  • 2
  • 11
  • @Supahupe I just get a nullpointerException when trying to use a method setQuestion in questioncontroller when i do it like that! I will edit my question for you to see my edits – Pateman Jul 11 '16 at 19:48
  • What is the root element of your FXML? Does it include the `fx:controller` tag, as Supahupe suggested, with the value of the (fully qualified) controller class name? If you continue to have issues, you might wish to supply your FXML in your question. – jewelsea Jul 11 '16 at 19:51
  • @jewelsea, can you give me an example of that cause I dont really understand – Pateman Jul 11 '16 at 19:52
  • 1
    See [Oracle FXML documentation](https://docs.oracle.com/javase/8/javafx/api/javafx/fxml/doc-files/introduction_to_fxml.html#controller_method_event_handlers) ``. See also related question: [Passing Parameters JavaFX FXML](http://stackoverflow.com/questions/14187963/passing-parameters-javafx-fxml) – jewelsea Jul 11 '16 at 19:55
  • @fabian You are right, I removed that statement. I will correct it above – Supahupe Jul 12 '16 at 08:24
  • @JohnTagliatelle I made an edit in my answer. Is there a stacktrace that you can add to your question? – Supahupe Jul 13 '16 at 08:55
  • @Supahupe when I initialized controller after pane I dont get a nullpointerException anymore, I just get some loading error. like this: [error code](http://textuploader.com/5ibe7) – Pateman Jul 13 '16 at 16:27
  • The error message says (quite below): "Can not set javafx.scene.control.TextField field tpmain.FXMLQuestionDocumentController.question to javafx.scene.control.TextArea" . Under http://textuploader.com/5iwwh (where you posted your question xml), you have a TextArea. In your controller, you use a TextField. That are different types :-) – Supahupe Jul 13 '16 at 16:39
  • 1
    @Supahupe you must be kidding me lol, it works ! thanks for your patience and help! – Pateman Jul 13 '16 at 17:04