Reputation: 53
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.
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)
Upvotes: 4
Views: 330
Reputation: 515
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();
}
}`
Upvotes: 1