-1

Update All I want to do is just save the value of the label to another class. This is my biggest problem and nothing seems to work.

I've been working on a javafx project for a few weeks. I was almost done but ran into trouble communicating information amoung classes. After 2 days, I still cant figure out why it wont work. Here is some code below:

Class where I initialize data:

 @FXML
 Label money; 
 @FXML
 int holder;
 @FXML
 Label tst;
 int currency;
 BankData bank;

 //this is where text for money label is set from user input
 public void presetMoney(ActionEvent e) { 
        if(e.getSource() == ten)    {
            currency += 10;
            money.setText(Integer.toString(currency));
        }
 //this is where I try to retrieve the value of money
  public void testing() {
        this.holder = Integer.parseInt(money.getText());        
        bank.storeData(holder);
        tst.setText(Integer.toString(holder));
    }

    public int getTesting() {
        return this.holder;
    }

BankData.java (Class where I'm trying to set the data):

 String data;
 public void storeData(String data) {
     this.data = data;
 }

But of course, I get this error:

Caused by: java.lang.NullPointerException
at application.TransactionScreenController.testing(TransactionScreenController.java:159)
... 58 more

Before I get redirected to some NullPointer post and get downvoted, I just wanted to know why my variable returns null when attempting to save it to another class. Clearly the variable "holder" is not null since I tested it by setting it to another label.

Here is a picture to help make it more clear

I successfully got text from the Label money and set it to int holder. Then I set the value of holder to the label tst. However, when I try to set the value of holder to another class, I get a nullpointer.

EDIT I initialized BankData bank = new BankData() and tried changing the variables to int. I just get 0 instead of null.

EDIT 2 So I tried FXML injection and now I get a class exception

public void trasComplete(ActionEvent e) throws IOException {            
        FXMLLoader loader = new FXMLLoader();   
        //methods to change screen not included because of irrelevance
        BankData n = loader.getController();
        n.storeData(holder);
}

Caused by: java.lang.ClassCastException: application.SecrurityScreenController cannot be cast to application.BankData
at application.TransactionScreenController.trasComplete(TransactionScreenController.java:173)
... 58 more
Syed Sadman
  • 117
  • 2
  • 12

2 Answers2

0

You never initialized your bank object in your constructor.

BankData bank = new BankData();

user681574
  • 553
  • 2
  • 15
  • If holder has the value of "0" then this would be correct. What does your money object text say when you try to run the testing function? – user681574 Jun 10 '18 at 19:46
  • I included a picture in my question. money is a label whose value is set to the sum of button clicks. Holder is an int which is supposed to take text from money and store it. Then BankData is supposed to store the value of holder(containing text from money) into its variable "data." – Syed Sadman Jun 10 '18 at 19:53
  • When you say you "get 0 instead of an error" - where do you get 0? In the "data" within the BankData object? Can you debug what is getting passed into that storeData function? I think you need to see exactly where the 0 or "0" (integer or string) is being generated. – user681574 Jun 10 '18 at 20:08
  • I created a method getTesting() and created an instance of the first class in main. I called getTesting and it returned 0. So I guess the problem is in the first class since holder remains 0 and that value gets passed onto BankData. This is what confuses me. "holder" can set a value to a label but it loses that value when trying to pass it to another class. – Syed Sadman Jun 10 '18 at 20:20
0

You need to share a model between your controller classes. There are some questions about this on Stack Overflow already.


For your case, the easiest and least disruptive solution would be to make BankData a singleton. This would make your BankData include:

public class BankData {

    private static final BankData INSTANCE = new BankData();

    // or make INSTANCE public, get rid of this method, and
    // use BankData.INSTNACE to access the instance
    public static BankData getInstance() {
        return INSTANCE;
    }

    // private constructor to stop any unwanted instantiations
    private BankData() {
        /* do any initialization */
    }

    // your other methods...

}

Then in both your controller classes you'd initialize your BankData with private BankData bank = BankData.getInstance();. You could also get rid of the field and simply call BankData.getInstance() any time you need to use it.


Edit

In your second edit you tried to set the instance but got a ClassCastException. That is because you did:

BankData bank = loader.getController();

which will throw said exception because loader.getController() returns the controller that was instantiated during load(). Instead, your code should look like:

SecrurityScreenController controller = loader.getController();
controller.getBankData().storeData(holder); 

Whether or not this code allows you to share data between controllers depends on how you implement this in the larger scope of the project. I just wanted to show you why you were getting a ClassCastException.

Slaw
  • 37,820
  • 8
  • 53
  • 80
  • I didn't make BankData a singleton (although i will do it later on) but I followed what you said about the ClassCastException and i was able to get the data from holder and pass it onto the desired screen. Thank you. – Syed Sadman Jun 10 '18 at 22:17