JRJurman
JRJurman

Reputation: 1728

Defining a method in a for Loop JAVA

So, I'm trying to define a set of methods for a large set of buttons, and I figured I could do it in a for loop, but I'm getting a syntax error which I can't decipher... Here's a simplified version of the code I want to use... The error is: "Syntax error on token(s), misplaced construct(s)"

JMenu blocks = new JMenu("Block");
menuBar.add(blocks);

for (int i=0; i < 9; i++){
  public void action() {
      System.out.println(i+"");
  }
  JMenuItem blockName = new JMenuItem(i+"");
  blockName.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent arg0) {
          action();
      }
  });
  blocks.add(blockName);
}

Upvotes: 2

Views: 5082

Answers (7)

basiljames
basiljames

Reputation: 4847

You can also do this

    for (int i = 0; i < 9; i++) {
        JMenuItem blockName = new JMenuItem(i + "");
        blockName.setAction(new MyAction(i));
        blocks.add(blockName);
    }
}

class MyAction extends AbstractAction {
    int param;

    public MyAction(int myParameter) {
        param = myParameter;
    }

    public void actionPerformed(ActionEvent e) {
        System.out.println(String.valueOf(param));
    }
}

Upvotes: 1

Dave
Dave

Reputation: 4597

Delete your action method and place your code inside the ActionListener

  public void actionPerformed(ActionEvent arg0) {
      System.out.println(i+"");
      // ... etc.
  }

As others have mentioned in their answers, i will not be accessible from within actionPerformed. Specifically, see @dasblinkenlight's answer for a more thorough response.

Upvotes: 3

moonwave99
moonwave99

Reputation: 22817

You can'd define nested methods, just nested classes [inner classes], or a class nested in a method [local classes].

If you want your ActionListener to be aware of the i, you can't directly, or you will stumble upon such error:

local variable i is accessed from within inner class; needs to be declared final

so you should extend your JMenuItem, or better design your application in order to decouple UI from current model status.

Upvotes: 0

You can not have a method declartion insede for loop. The loop must be in a method body.

 private void init(JMenu blocks) {
   for (int i=0; i < 9; i++){

    JMenuItem blockName = new JMenuItem(i+"");
    blockName.addActionListener(new ActionListener() {
          public void actionPerformed(ActionEvent arg0) {
              handleAction(arg0);
          }
      });
    blocks.add(blockName);
  }
}


   public void handleAction(ActionEvent event) {

       Object source = event.getSource(); 

       if(source instanceof JMenuItem) {
           JMenuItem item = (JMenuItem) source;
           System.out.println(item.getName());
       ) 
   }

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726699

Java methods are not first-class objects (or second or third-class objects; in fact, methods are not objects at all). You need to move the method into one of the classes - either your top class, or the anonymous inner class that you defined, like this:

for (int i=0; i < 9; i++) {
    // You cannot access i from methods of the anonymous inner class
    // because it is not final, but you can make a final copy
    final int iCopy = i;
    JMenuItem blockName = new JMenuItem(i+"");
    blockName.addActionListener(new ActionListener() {
        // It is OK to define additional methods here:
        public void action() {
            System.out.println(iCopy+"");
        }
        public void actionPerformed(ActionEvent arg0) {
            action();
        }
    });
    blocks.add(blockName);
}

Upvotes: 2

Robin
Robin

Reputation: 36611

That is simply not valid Java. Consider creating an Action instance in your for loop and use that action to back the JMenuItem, e.g.

JMenu blocks = new JMenu("Block");
menuBar.add(blocks);

for (int i=0; i < 9; i++){
    Action action = new AbstractAction(){
      public void actionPerformed( ActionEvent e ){
        System.out.println( "Whatever but not i as that cannot be accessed" );
        System.out.println( "or you need to introduce a final variable" );
      }
    };  
    JMenuItem blockName = new JMenuItem(i+"");
    blockName.setAction( action );  
    blocks.add(blockName);
}

Upvotes: 1

You are defining a new method inside another method:

  public void action() {
      System.out.println(i+"");
  }

You need to extract this outside of the current method.

Upvotes: 2

Related Questions