简体   繁体   中英

Java: Why would a variable set outside of a for loop change inside of the for loop

I am a fairly new programmer working on a game in java (as a side project). I'm learning a lot, and I've managed to create a surprising amount of the game without needing help. I could probably even just omit this function and it wouldn't ruin the aesthetic!

I would like to make it work though, and I am perplexed. I set the tempColor variable outside of a for loop, but it changes inside the for loop... but only the second time it is activated, and only to the variable that was used the first time it ran. For example: If I change the red teams score, it runs through and my JOption shows the red - red match and it changes the red teams score only. If I then change blue teams score, it runs through, finds the blue - blue match changes the score, then goes back through the loop a second time until it finds the red - red "match" and changes that score to the same value as the blue score.

I've been over it top to bottom and I can't find what would cause this. I am hoping someone might take pity on me and help me learn something.

Another action I don't understand, I have a main class variable, Choice, but it wasn't passing into the internal code, so I had to transfer it to the tempColor variable. I also noted that I cannot reset it inside the method (something about needing to be "final." I assumed this is because it is a temporary variable that should not exist after the loop executes, but given the behavior of the program... I"m Not sure if this is important, but thought it might possibly be relevant.

The operation starts with the menu item:

private void mniAdjustScoreActionPerformed(java.awt.event.ActionEvent evt) {  
adjustScore();
}  

Which runs:


    private void adjustScore() {
        //FIXME changing the first team AND the second team's score when called a second time for some unknown reason... an unexpected loop?
        //set components visibility
        df.CT.lblChoose.setText("Which team needs adjustment?");
        setCTButtons();
        df.CT.setVisible(true);
        df.CT.btnAdjust.setVisible(false);
        df.CT.jspAdjust.setVisible(false);
        df.CT.txtName.setVisible(false);
        
        //Set Choice color by button and pass to changeScore method
        df.CT.btnRedTeam.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Choice = "red";
                changeScore();
                Choice = "";
            }
        });
        
        df.CT.btnBlueTeam.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Choice = "blue";
                changeScore();
                Choice = "";
            }
        });
        df.CT.btnCyanTeam.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Choice = "cyan";
                changeScore();
                Choice = "";
            }
        });
        df.CT.btnYellowTeam.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Choice = "yellow";
                changeScore();
                Choice = "";
            }
        });
        df.CT.btnGreenTeam.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Choice = "green";
                changeScore();
                Choice = "";
            }
        });
        df.CT.btnPurpleTeam.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Choice = "purple";
                changeScore();
                Choice = "";
            }
        });
    }

Once the button is pressed, it runs the changeScore() method:


private void changeScore(){

        //TODO Fix me - running adjust score a second time changes both the second team and the first team. some kind of unintended loop???

        //set components visibilty for second part of operation
        df.CT.lblChoose.setVisible(true);
        df.CT.jspAdjust.setVisible(true);
        df.CT.btnAdjust.setVisible(true);
        df.CT.txtName.setVisible(false);
        
        //set tempColor to Choice value (LOOK UP LATER - not sure why this is necessary)
        String tempColor = Choice;
        
        //adjust button 
        df.CT.btnAdjust.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                //get value from spinner and assign to tempScore
                int tempScore = (Integer) df.CT.jspAdjust.getValue();

                //iterate through the teams to find the one whose TeamColor property matches tempColor
                for(int i=0; i<df.orderedTeamList.size(); i++){
                    String tempColor2 = df.orderedTeamList.getElementAt(i).getTeamColor();

                    //REMOVELATER - option pane to show values in each iteration
                    JOptionPane.showMessageDialog(null, "Choice: "+ Choice + "\n tempColor: " + tempColor + "\n tempScore: " + tempScore + "\n tempColor2: " + tempColor2,
                        "NOTE", JOptionPane.ERROR_MESSAGE);
                   
                    // look for a color match and assign values to the correct team
                    if (tempColor2.equals(tempColor)){
                        if (tempColor.equals("red")){
                            df.txtScoreT1.setBackground(Color.RED);
                 
                            df.orderedTeamList.getElementAt(i).setTeamScore(tempScore);
                        }
                        else if (tempColor.equals("blue")){
                            df.txtScoreT2.setBackground(Color.RED);
                            df.orderedTeamList.getElementAt(i).setTeamScore(tempScore);
                        }
                        else if (tempColor.equals("cyan")){
                            df.txtScoreT3.setBackground(Color.RED);
                            df.orderedTeamList.getElementAt(i).setTeamScore(tempScore);
                        }
                        else if (tempColor.equals("yellow")){
                            df.txtScoreT4.setBackground(Color.RED);
                            df.orderedTeamList.getElementAt(i).setTeamScore(tempScore);
                        }
                        else if (tempColor.equals("green")){
                            df.txtScoreT5.setBackground(Color.RED);
                            df.orderedTeamList.getElementAt(i).setTeamScore(tempScore);
                        }
                        else if (tempColor.equals("purple")){
                            df.txtScoreT6.setBackground(Color.RED);
                            df.orderedTeamList.getElementAt(i).setTeamScore(tempScore);
                        }
                        else{
                            JOptionPane.showMessageDialog(null, "Team is not active!",
                                "Team Error", JOptionPane.ERROR_MESSAGE);
                        }
                    }
                }
            // refresh point totals and close the CT window
            updatePoints();
            df.CT.setVisible(false);
            }
        });
    }

I had originally tried to setup a joption dialog to get this info, but I couldn't get it to read. Then I tried passing the color into the method, but it had the same effect I'm experiencing now... well that and it didn't change the score when I had it set up that way. This just seems weird and illogical.

I added the joption pane to track the variables, which is how I found where and what it was doing. I'm just stumped as to what to do with that information!

Also, I'm aware my code is not as efficient as it could be. I'm still learning and applying new techniques as I learn them. I only started working in java like 2 months ago, so my strategy is to make it work then improve it.

Don't dynamically add ActionListener s to your buttons - add them once when creating the components.

What happens is this:

  • you click the button for the red team. This sets Choice to "red" and calls changeScore()
  • changeScore() adds an ActionListener to the adjust-button with tempColor having "red"
  • you click the button to adjust the teams score. The previously added ActionListener for the red team runs and adjusts its score.
  • you click the button for the blue team. This sets Choice to "blue" and calls changeScore()
  • changeScore() adds a second ActionListener to the adjust-button with tempColor having "blue"
  • you click the button to adjust the teams score. Both ActionListener s that you added (one for the blue team, one for the red team) run and adjust the scores of their team.

If you were to click the button for the "cyan" team your could would add a third ActionListener which would then change the scores of three teams.

This fix is - as I've written in the first paragraph: don't dynamically add ActionListener s to your buttons.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM