更改场景时的JavaFX空指针表达式

时间:2019-05-02 15:50:08

标签: java javafx

我在更改JavaFX场景时遇到问题。当我尝试切换场景时,出现空指针异常,但是我使用调试器对其进行调试,它告诉我舞台指针为空。我注意到它没有找到stage的start方法的构造函数声明,因此我为整个类创建了一个变量。我不确定为什么该阶段指针为null,因为我确实在类中声明了变量。

这是主控制器切换场景的方法:

onstart.changeScene("password.fxml");

这是OnStart类,用于切换场景:

public class OnStart extends Application{
Parent root;
private Stage stage;
//private AnchorPane mainLayout;
//private HashMap<String, Pane> screenMap = new HashMap<>();
private Scene main;
FXMLLoader loader = new FXMLLoader();

@Override
public void start(Stage stage) throws Exception{
    this.stage = stage;
    root = loader.load(getClass().getResource("mainmenu.fxml"));

    main = new Scene(root);

    this.stage.setTitle("Photo Encryptor 9000");
    this.stage.setScene(main);
    this.stage.show();
}

public Parent getRoot() {
    return root;
}

public Scene getScene() { return main; }

public void changeScene(String fxml) throws IOException {
    root = loader.load(
            getClass().getResource(fxml));
    stage.getScene().setRoot(root);
}
}

这也是错误(第44行是stage.getScene.setRoot(root)方法):

Caused by: java.lang.NullPointerException
at com.example.helloworld.OnStart.changeScene(OnStart.java:44)
at com.example.helloworld.MainController.encryptpress(MainController.java:99)

MainController:

public class MainController implements Initializable{

public String path, name;
private String passwordPlainText;
private boolean hasname;
private File f;
FileWriter out;
OnStart onstart = new OnStart();
BufferedImage image;
int widthofimage, heightofimage, numberofpixils;
AES aes = new AES();
@FXML
private TextField passwordtextbox;
FileReader read;


@FXML
private AnchorPane rootpane;

@Override
public void initialize(URL url, ResourceBundle rb){
}

@FXML
private void encryptpress(ActionEvent event) throws Exception {
    //byte[] converter; //sample of encrypting and decrypting
    //String output = "hello";
    //converter = output.getBytes();
    //System.out.println(output);
    //converter = aes.encrypt(output, "noooo");
    //System.out.println(converter);
    //output = aes.decrypt(converter, "noooo");
    //System.out.println(output);

    //File chooser
    FileChooser fileChooser = new FileChooser();
    fileChooser.setTitle("Open Resource File");
    fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("JPEG Files", "*.jpg"));
    f = fileChooser.showOpenDialog(null);    //f is the image
    //Checks if a jpg file was chosen
    if(f == null) {//if a file wasn't chosen...
        AlertBox.display("Error", "No file was chosen");
        return;
    }
    read = new FileReader();
    out = new FileWriter("passwords.txt", true);
    path = f.getAbsolutePath();//gets absolute path of file
    name = f.getName();//gets name of file
    System.out.println("Does file exist in passwords file: " + read.checkforfile(name)); //test - should output true if a file with name exists

    if( read.checkforfile(name) ){ //goes back to parent node
        if( read.hasHash(name) ){
            AlertBox.display("Error", "This filename already has a password.");
            //if true, then go back to main menu and display: "This filename already has a password."
            Parent parent = onstart.getRoot(); //Not sure if this gets the pointer to the root or just a copy of the root
            Scene parentscene = onstart.getScene();
            Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow();
            window.setScene(parentscene);
            window.show();
            return;
        }
        hasname = true; //maybe close this automatically
        //skips the addname process if hasname is true
    }else { //adds the name of the image to the file if the image does not already exist

        hasname = false; // waits to write the name just incase the user exits out of the program early without choosing a password
    }

    if(hasname == false){
        out.write(name);
    }
    //System.out.println(name);
    out.write(name);

    image = ImageIO.read(f);
    if(onstart.getRoot() != null) {System.out.println("Root is clear");}
    if(onstart.getStage() != null) {System.out.println("Stage is clear");}
    if(onstart.getScene() != null) {System.out.println("Scene is clear");}
    onstart.changeScene("password.fxml");//////////////Error



    //This copies the file and places it in the same directory
    String newfile = "Encrypted" + f.getName();
    File EncryptedImage = new File(newfile);
    BufferedImage originalImage = ImageIO.read(f);
    BufferedImage newImage = new BufferedImage(originalImage.getWidth(), originalImage.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
    widthofimage = originalImage.getWidth();
    heightofimage = originalImage.getHeight();
    numberofpixils = widthofimage * heightofimage;
    int add = 0;
    byte[] bytes = new byte[numberofpixils];
    for (int x = 0; x < originalImage.getWidth(); x++) {
        for (int y = 0; y < originalImage.getHeight(); y++) {
            bytes[add] = (byte) originalImage.getRGB(x, y);
            add++;
        }
    }
    String s = new String(bytes);
    String passwordtest = "password";
    //s = aes.encrypt(s, passwordtest); //passwordplaintext is real passowrd holder
    bytes = s.getBytes();

    add = 0;

    for (int x = 0; x < originalImage.getWidth(); x++) {
        for (int y = 0; y < originalImage.getHeight(); y++) {
            newImage.setRGB(x, y, bytes[add]);
            add++;
        }
    }
    ImageIO.write(newImage, "JPG", EncryptedImage);
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //ImageIO.write(newImage, "JPG", f2);//this creates a new image that is now encrypted
    //System.out.println(image);

}


/*@FXML
private void dgxsd(ActionEvent event){
    String test = "Hello";
    String passwordtest = "password";
    System.out.println(test);
    test = aes.encrypt(test, passwordtest); //passwordplaintext is real passowrd holder
    System.out.println(test);
    test = aes.decrypt(test, passwordtest);
    System.out.println(test);
}*/


@FXML
private void decryptpress(ActionEvent event) throws IOException {
    //if passwords.txt is not empty: AnchorPane pane = FXMLLoader.load(getClass().getResource("password2.fxml"));
    FileChooser fileChooser = new FileChooser();
    fileChooser.setTitle("Open Resource File");
    fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("JPEG Files", "*.jpg"));
    File f = fileChooser.showOpenDialog(null);
    if(f == null) {//if a file wasn't chosen...
        AlertBox.display("Error", "No file was chosen");
        return;
    }
    read = new FileReader();
    out = new FileWriter("passwords.txt", true);
    path = f.getAbsolutePath();//gets absolute path of file
    name = f.getName();//gets name of file
    System.out.println("Does file exist: " + read.checkforfile(name)); //test - should output true if a file with name exists
}


@FXML
private void Createpassword(ActionEvent event) throws IOException {
    passwordPlainText = passwordtextbox.getText();
    System.out.println(passwordPlainText);
    BufferedImage image = ImageIO.read(f);


   // doAESEncryption(passwordPlainText);
}

1 个答案:

答案 0 :(得分:2)

@kendavidson是正确的,您得到null的原因是MainController类中的这一行是您拥有的这一行

OnStart onstart = new OnStart();

使用null指针的原因是,您在创建该类的新实例时将其设置为null

要解决此问题,请在MainController类中创建一个看起来像这样的方法

public void setOnStartReference(OnStart onStartReference){
    onstart = onStartReference;
}

并删除MainController类顶部的= new OnStart();,使其现在看起来像这样

OnStart onstart;

现在,在OnStart类中,您需要先设置引用,然后才能调用OnStart类中的任何内容

MainController controller = loader.getController();
controller.setOnStartReference(this);

但是请确保将其放在loader.load...