0

I recently picked up javaFx and I am trying to learn in on my own. I have this few clases that were created to mess around with the GUI I am creating, said classes are:

Library, AccHolder, Bibliography. A library can have many AccHolders and Many Bibliography, then I have these two classes:

import java.util.ArrayList;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;


public class Main extends Application{

    Stage window;
    Button b1;
    AccHolder userInputFromAcc; 

    public static void main(String[] args){
        launch(args);
    }

    @Override
    public void start(Stage primaryStage){
        Library lib = new Library();

        window = primaryStage;
        window.setTitle("Main Window");
        b1 = new Button("Press Me!");
        b1.setOnAction(
                e->{
                    userInputFromAcc = MainWindow.display("New Card Holder");
                    lib.addAccount(userInputFromAcc);
                    lib.printAllAccounts();
                });

        StackPane layout = new StackPane();
        layout.getChildren().add(b1);

        Scene scene = new Scene(layout,1300, 650);
        window.setScene(scene);
        window.show();

    }
}

and

import java.util.ArrayList;
import javafx.beans.binding.BooleanBinding;
import javafx.geometry.Insets;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;

public class MainWindow  {
    private static AccHolder x;
    public static AccHolder display(String title){
        Stage window = new Stage();
        window.initModality(Modality.APPLICATION_MODAL);
        window.setTitle(title);
        ArrayList<String> list = new ArrayList<>();

        GridPane grid1 = new GridPane();
        grid1.setPadding(new Insets(10,10,10,10));
        grid1.setVgap(8);
        grid1.setHgap(10);

        //Aplicants's name and text field:
        Label apNameLabel = new Label("Aplicant's Name: ");
        GridPane.setConstraints(apNameLabel, 0,0);

        TextField apNameInput = new TextField();
        GridPane.setConstraints(apNameInput, 2,0);
        apNameInput.setPromptText("Name");

        //Aplicant's age
        Label apAgeLabel = new Label("Aplicant's Age: ");
        GridPane.setConstraints(apAgeLabel, 0,1);

        TextField apAgeInput = new TextField();
        GridPane.setConstraints(apAgeInput, 2,1);
        apAgeInput.setPromptText("Enter Age ");

        //Aplicant's ID card
        Label apIDlabel = new Label("Aplicant's ID Card Number: ");
        GridPane.setConstraints(apIDlabel, 0,2);

        TextField apIDInput = new TextField();
        GridPane.setConstraints(apIDInput, 2,2);
        apIDInput.setPromptText("Enter ID ");

        Button b1 = new Button("Create Account");
        GridPane.setConstraints(b1, 0,6);

        BooleanBinding bb= new BooleanBinding(){
            {
                super.bind(apNameInput.textProperty(), 
                        apAgeInput.textProperty(), 
                        apIDInput.textProperty());
            }
            @Override
            protected boolean computeValue() {
                return (apNameInput.getText().isEmpty() 
                        || apAgeInput.getText().isEmpty()
                        || apIDInput.getText().isEmpty());

            }
        };
        b1.disableProperty().bind(bb);
        b1.setOnAction(e->{
            String a,c;
            int b = 0;
            a = apNameInput.getText();
            try{
                b = Integer.parseInt(apAgeInput.getText());
            } catch(Exception e1){
                apAgeInput.setText("");
            }
            c = apIDInput.getText();
            // Save User Input into an array list.  
               x = new AccHolder(a, b, c);
            window.close();
        } );


        Button b2 = new Button("Close");
        GridPane.setConstraints(b2, 1,6);
        b2.setOnAction(e-> window.close() );

        grid1.getChildren().addAll(apNameLabel, apNameInput, apAgeLabel, apAgeInput, apIDlabel, apIDInput, b1, b2);

        Scene scene = new Scene(grid1, 500, 200);
        window.setScene(scene);
        window.setResizable(false);
        window.show();

        return x;

    }

}

Basically the button in the main opens the second window, that window has the textfields to be filled with the user info, whati intended was to return those values after being collected and create an object of tipe AccHolder in the Main and save it to lib.

I ran into several complications, one of them being that as soon as the first button is pressed the program gives me an error as if the information is not being collected from Window 2 and passed to Window 1.

Notice that I never wanted to create an object in window 2, my main idea was to collect info in its pure form and then pass it to window 1, then create the object in window 1(Main).

I am really new to javaFx and lanmda expressions, therefore I might not be using them effectively. Here is a part of the error that prints out as soon as I press b1 on window 1:

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at Library.printAllAccounts(Library.java:45)
    at Main.lambda$0(Main.java:30)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)... 

etc

Have no clue why is this happening, this is really stalling my learning process.

halfer
  • 19,824
  • 17
  • 99
  • 186
Carlos Luis
  • 213
  • 2
  • 17

1 Answers1

1

In MainWindow.display() you do not set the variable x until the button b1 is actually pressed. However, you return the value immediately after showing the window. So the returned value will be null.

You haven't actually posted the code that throws the exception (line 45 of Library), but I assume it tries to call a method on the value passed into the addAccount method (which is null, as explained above).

Instead of calling

window.show();

in MainWindow.display(), call

window.showAndWait();

This will show the window and block execution until it closes.

There may be other errors, but this is most likely what is causing the null pointer exception you observed.

James_D
  • 201,275
  • 16
  • 291
  • 322
  • I have been trying to solve this for an hour now lol, it drove me to a breaking point. May I ask if you can recommend me some good literature being digital or physical that can help me learn how to improve my GUI skills in JavaFx, and learn the best practices? Did i do fine with creating an object in the secondary window, or is it the norm to feed the info back and create the object in the main? – Carlos Luis Sep 10 '15 at 02:04
  • What's considered best practice is really to store the data in a separate class (called a "model"), and share an instance of that class among the various classes that process user input (called "controllers" or "presenters", depending on which variation of that pattern you use). Have a look at my answer to http://stackoverflow.com/questions/32342864/applying-mvc-with-javafx/32343342#32343342 for a quick example of what I mean there. However, this is quite advanced for where you are now: if you are still figuring out how to debug NPEs you just need to get more practice with using OOP in general – James_D Sep 10 '15 at 02:08