Question

I am making a stat keeping program to practice my GUI skills in Java.

I have a program that records the statistics of basketball players by hitting a JButton under their name. Then it adds the stat to the running total and updates the scoreboard.

It has come time for me to create an undo button.

So, every time an action is performed, I add the source button to a stack of JButtons. There is some casting involved, so it ends up like this:

JButton source = (JButton) e.getSource();
theStack.push(source);

Later on, in the actionPerformed method I try to call by undo function:

if(source.getText().equals("Undo")){
    System.out.println("Undo");
    JButton last = this.theStack.pop();
    System.out.println(last.getText()); //Works fine.
    System.out.println(last.getName()); //Produces a null value.
    int player = Integer.parseInt(last.getName().trim());
    undo(player, last.getText(), activePlayers);
}

Why am I getting a null for the name. Eclipse is throwing an exception when it tries to convert the name to an int because it is converting a null value. I use the .getName() in other parts of the actionPerformed, but not here?

My name setting code, done many times in a for loop.

output[i][j] = new JButton("Make Two Points");
output[i][j].setName(i + "");

The problem in it's simplest form.

public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
        ArrayList<Integer> activePlayers = new ArrayList<Integer>();
        activePlayers.add(player0Select.getSelectedIndex());
        activePlayers.add(player1Select.getSelectedIndex());
        activePlayers.add(player2Select.getSelectedIndex());
        activePlayers.add(player3Select.getSelectedIndex());
        activePlayers.add(player4Select.getSelectedIndex());

        JButton source = (JButton) e.getSource();
        theStack.push(source);

        if(source.getText().equals("Make Two Points")){
            this.makeTwoPoints(source.getName(), activePlayers); //source.getName() works here.
            System.out.println("Two Points");
        }
        if(source.getText().equals("Undo")){
            System.out.println("Undo");
            JButton last = this.theStack.pop();
            System.out.println(last.getText());
            System.out.println(last.getName()); //last.getName() produces null here.
            int player = Integer.parseInt(last.getName().trim());
            undo(player, last.getText(), activePlayers);
        }
}
Was it helpful?

Solution

Because you never set the JButton's name, and nor should you. Every Component has a name property that can be set via the setName(...) method, and if the setter method is never called, then that name is null. But what is the significance of this property? Not much here.

If this were my project, I wouldn't stack JButtons, but rather would stack model objects, or perhaps controls (Actions). Let's not mix our models with our views.


Edit

For a simple example of what I mean,

You could have a StatAction enum that had your three (or more statistic actions), e.g.,

public enum StatAction {
   MAKE_2_PTS("Make Two Points"), MISS_2_PTS("Miss Two Points"), 
   MAKE_3_PTS("Make Three Points");

   private String text;

   private StatAction(String text) {
      this.text = text;
   }

   @Override
   public String toString() {
     return text;
   }

   public String getText() {
      return text;
   }

}

And you could have a Player class that could include a name field as well as a List<StatAction>, for example it could have...

public class Player {
   private String name;
   private List<StatAction> statActionList = new ArrayList<>();

   // ....

   public String getName() {
      return name;
   }

   public void addStatAction(StatAction statAction) {
      statActionList.add(statAction);
   }

   public void removeStatAction(StatAction statAction) {
      statActionList.remove(statAction);
   }

   public void removeLastStatAction() {
      if (statActionList.size() > 0) {
         statActionList.remove(statActionList.size() - 1);
      }
   }

   //.....

}

And then undo could remove the last StatAction from a Player's list. The display of Stats could then change on the fly via listeners.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top