This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 3 years ago.
This is my first time working with JavaFX, I tried to create a KeyListener (KeyTyped) that reacts to the whole scene, since I don't like to always click into textfields/areas etc.
So I got the following code:
package view;
import controller.Function;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
public class MainGame implements Initializable {
public TextField txtText;
protected String word = "ABC";
void start(ActionEvent event) throws IOException {
URL url = new File("src/main/java/view/MainGame.fxml").toURI().toURL();
Parent MainGame_parent = FXMLLoader.load(url);
Scene MainGame_scene = new Scene(MainGame_parent);
Stage primaryStage_stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
primaryStage_stage.setScene(MainGame_scene);
primaryStage_stage.show();
MainGame_scene.addEventFilter(KeyEvent.KEY_TYPED, (KeyEvent ev) -> {
//System.out.println(Function.decrypt(word, txtText.getText(), ev.getCharacter().charAt(0)));
//txtText.setText(Function.decrypt(word, txtText.getText(), ev.getCharacter().charAt(0)));
//Function.won(word, txtText.getText());
});
}
#Override
public void initialize(URL url, ResourceBundle rb) {
txtText.setText(Function.encrypt(word));
}
}
Now, this code itself works, it just doesn't do anything if a key is pressed. The three comments would be responsible for that, but whenever I uncomment one or more, they cause a NullPointerException. I have already tried to print the different values. Every value worked except for txtText, which caused a NullPointerException.
I have tried moving it to different places, putting it into an own function, putting it into initialize, not declaring it in the class body but in the function and I also tried putting the rest of the start method in the constructor. Sadly none of those things worked.
I have no idea what to do and how to fix this.
Thanks for any help!
Your TextField txtText is not initialized before you try to use it. You should do
public TextField txtText = new TextField();
instead of
public TextField txtText;
Related
I'm making a simple program wherein I am trying to add a string from a TextField to a ListView in another scene. The problem is I am getting a NullPointerException when I pass the string to the method which will add it to the List.
Here is the code for controller for the main scene:
import java.io.IOException;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
public class MainPageController {
#FXML TextField txtfield;
public void addButton(ActionEvent event) {
String a=txtfield.getText();
FXMLLoader loader= new FXMLLoader();
loader.setLocation(getClass().getResource("/progra/view/ListView.fxml"));
ListController obj=loader.getController();
obj.addList(a);// <----NullPointerException
}
public void openList(ActionEvent event) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/program /view/ListView.fxml"));
Parent root1 = (Parent) fxmlLoader.load();
Stage stage = new Stage();
stage.setScene(new Scene(root1));
stage.show();
}
}
Here is the code for the controller of the list scene:
import javafx.fxml.FXML;
import javafx.scene.control.ListView;
public class ListController{
#FXML
ListView<String> listofstrs;
public void addList(String a) {
listofstrs.getItems().add(a);
}
}
What do I need to do to fix it? If I may add, is it possible to add variables to a ListView (or any other text containers) in another stage/scene without opening the stage/scene where it is contained, and when you open it you will see the things you added? If so, what do i need to add?
Because you are calling the getController() method, and the controller is not set within the Java source, you must have the controller defined within your fxml file. Can you post the fxml source?
In your fxml, your root element should have the fx:controller attribute set to the class path of the controller, e.g:
fx:controller="com.class.path.to.ListController
I have this exception when trying to parse a JSON file with GSON:
Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: class com.sun.javafx.jmx.HighlightRegion declares multiple JSON fields named hash
I have tested a little to what causes this, and I found that it only occurs when I create a Object that has an Event object as a member. In this case, I am trying to create a List of Quest objects that eventually have Event objects.
package Quests;
import Events.EventSequence;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class Quest {
public static void parseQuest() {
Gson gson = new Gson();
FileReader questGSON;
try {
questGSON = new FileReader(QUEST_FILE);
} catch (FileNotFoundException e) {
e.printStackTrace();
return;
}
JsonObject questJSON = gson.fromJson(questGSON, JsonObject.class);
questList = new ArrayList<>();
for(Map.Entry<String, JsonElement> element : questJSON.entrySet()) {
questList.add(gson.fromJson(element.getValue(), Quest.class));
}
}
}
I am using javafx in that class in the following way:
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Button;
public abstract class Event implements EventHandler<ActionEvent> {
// members of this class
private String title, text;
private Button[] buttonSet;
protected Entity other;
protected Event nextEvent;
public abstract Event chooseNewEvent(String command);
#Override
public void handle(ActionEvent event) {
// Get the name of the button
String command = ((Button) event.getSource()).getText();
displayNewEvent(chooseNewEvent(command));
}
}
The only information I could find regarding this was:
https://github.com/wpilibsuite/shuffleboard/issues/358
Could someone point me in some direction to fix my bug?
I found out that it was a Button array from javafx.scene.control.Button in my Event class that was causing the problem. I fixed it by making it transient so it would get ignored by GSON and not cause any problems.
Nevertheless, I have no idea why the Button array would cause this exception. Any thoughts?
I made an application in Scene Builder on one FXML. I am making a server with JavaFX so I can learn JavaFX and get more familiar with Java's networking libraries.
I have a server terminal Tab and additional tabs within a TabPane. I wanted to make classes that extend upon the main controller class to handle components in each tab.
While trying to implement this I found that the FXMLLoader won't be able to read things if the #FXML annotated variables are static. And the #FXML annotated event listener method won't be read if that is static either.
And if I try any kind of workaround I get nullpointerexceptions when trying to change text in the TextArea. I really don't want to have to use multiple FXML files but it's seeming like I'll have to because if I can't make these static then it just won't work.
Within the Server Terminal Tab there is a TextArea, a TextField, and a Button.
Here's my working code:
package me.Cronin.Keith.JavaServer;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;
public class JavaServer extends Application {
#FXML
public Button btnSendCommand;
#FXML
public TextField consoleInputField;
#FXML
public TextArea serverTerminal;
public static FXMLLoader fxmlLoader = new FXMLLoader(JavaServer.class.getResource("JavaServer.fxml"));
public static void main(String[] args)
{
launch(args);
}
#Override
public void start(Stage stage) throws IOException
{
Parent p = fxmlLoader.load();
Scene scene = new Scene(p);
stage.setTitle("Java Server v1.0");
stage.setScene(scene);
stage.show();
}
#FXML
public void clickSendCommand(MouseEvent event)
{
serverTerminal.setText("I got clicked..");
}
}
Here's the other class that I don't know what to do with yet:
package me.Cronin.Keith.JavaServer.Terminal;
import me.Cronin.Keith.JavaServer.JavaServer;
public class Terminal extends JavaServer {
public static void logTerminal(String msg)
{
}
}
Is there anything I can do to change this to support what I want to do?
I want to be able to control the variables (JavaFX Components from FXML) in JavaServer.class with my other classes that extend upon it.
I have seen this question here:
Multiple controller for one FXML file
But it doesn't answer my question.
It's seeming like I'd have to put everything in the main controller class or have multiple Fxml files.
I was able to make this work by replacing my Terminal class with this:
Terminal.java
package me.Cronin.Keith.JavaServer.Terminal;
import me.Cronin.Keith.JavaServer.JavaServer;
public class Terminal extends JavaServer {
public static void logTerminal(String msg)
{
JavaServer mainController = fxmlLoader.getController();
mainController.serverTerminal.setText(msg + "\n");
}
}
So the answer is YES you can.
In JavaServer.java I just called Terminal.class statically and then used the static method logTerminal() within it which worked. I extended JavaServer.java in Terminal.java so I could statically call the controller's FXMLLoader.
I'm trying to create a game prediction system in Java with GUI based on JavaFX using scene builder. It contains a HashMap containing a game object in which there is an ArrayList containing the participating athletes. Both of which will be decided by the user at runtime. Only a certain type of athletes will be eligible for participating in a certain type for a game, for example, swimmers will be able to participate only in swimming games. I can get the eligible athletes at by matching their types with game object and athlete object, but how do I create the checkboxes(for the eligible athletes at runtime?
You can use following approach to add or remove checkboxes at runtime
package com.grsdev.stackoverflow.question170919.pack02;
import javafx.application.*;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
* #author gaurav salvi
*
*/
public class JavaFxCheckBoxDemo extends Application{
private static VBox root;
private static CheckBox box=new CheckBox("Apple");
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
root=new VBox();
Button button=new Button(" toggle ");
button.setOnAction(JavaFxCheckBoxDemo::buttonClicked);
root.getChildren().add(button);
root.getChildren().add(box);
Scene value=new Scene(root,200,200);
stage.setScene(value);
stage.show();
}
private static void buttonClicked(ActionEvent event){
if(root.getChildren().contains(box)){
root.getChildren().remove(box);
}else{
root.getChildren().add(box);
}
}
}
I think, dynamically creating objects in Scene Builder and linking them in the controller on basis of their ID would very difficult if not impossible. One possible workaround for the given problem would be adding several static objects and set their visibility to hidden. As and how athletes were created and getting added to the ArrayList in the Game object I changed the visibility for the given checkbox.
I have a TextField and I would like the contents of the field to be restored to their previous value when I press Esc which is expected behaviour on most systems (I have no idea why JavaFX doesn't do this by default).
To this end I tried to use TextField.cancelEdit() but it appears that this is doing nothing.
Here is a SSCCE
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.stage.Stage;
public class UiTest2Controller extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage aPrimaryStage) throws Exception {
final TextField field = new TextField();
field.setOnAction(aEvent -> {
System.out.println("Action");
});
field.setOnKeyPressed(aEvent -> {
if (aEvent.getCode() == KeyCode.ESCAPE) {
System.out.println("Escape");
field.cancelEdit();
field.getParent().requestFocus();
}
});
field.setPromptText("Hello World...");
aPrimaryStage.setScene(new Scene(new Group(field)));
aPrimaryStage.show();
}
}
Steps to reproduce:
Type something in the text field
Press Esc
Expected behaviour: The field returns to previous value (empty first time) and focus is lost.
Actual behaviour: The fiels retains its value at the time and focus is lost.
I am not sure about the specifics, but it seems to work as expected if the TextField has a TextFormatter assigned:
field.setTextFormatter(new TextFormatter<>(TextFormatter.IDENTITY_STRING_CONVERTER));