5
votes

Comment résoudre des variables référencées locales dans une boucle for?

J'écris une application Swing et j'essaie de créer un menu où chaque élément de menu a son propre action :

Voici comment je voulais Résolvez ceci:

private void createGameLevelMenuItems(JMenu menu){
    for (int i = 0; i<10; i++) {
        JMenuItem item = new JMenuItem(new AbstractAction("Level-" + i) {
            @Override
            public void actionPerformed(ActionEvent e) {
                game.loadGame(i);
                board.refresh();
                pack();
            }
        });
        menu.add(item);
    }
}

Cependant, je ne peux pas utiliser loadGame (i) , car il dit que i devrait être final. J'en comprends la raison, mais je ne sais pas comment contourner ce problème.


1 commentaires

Vous pouvez simplement créer une classe implémentant AbstractAction, stocker la variable i in instance et la fournir via le constructeur.


3 Réponses :


2
votes

Pour ajouter un exemple à mon commentaire ci-dessus. Vous pouvez simplement créer une classe implémentant AbstractAction, stocker la variable i in instance et la fournir via le constructeur:

private void createGameLevelMenuItems(JMenu menu){
    for (int i = 0; i<10; i++) {
        JMenuItem item = new JMenuItem(new LoadAction(i));
        menu.add(item);
    }
}

private class LoadAction extends AbstractAction {
    private int i;

    public LoadAction(int i) {
        super("Level-" + i);
        this.i = i;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        game.loadGame(i);
        board.refresh();
        pack();
    }
};

Cela suppose que le jeu et le plateau sont des variables finales dans la classe d'encapsulation, mais puisque vous avez juste un problème avec i , je suppose que c'est le cas.


0 commentaires

4
votes

Petite astuce: définissez une variable finale à chaque itération de la boucle qui prend la valeur (non finale) de i et utilisez-la:

private void createGameLevelMenuItems(JMenu menu){

  for (int i = 0; i<10; i++) {
    final int j = i;   // <--- this line do the thing
    JMenuItem item = new JMenuItem(new AbstractAction("Level-" + j) {
        @Override
        public void actionPerformed(ActionEvent e) {
            game.loadGame(j);
            board.refresh();
            pack();
        }
    });
    menu.add(item);
  }
}


0 commentaires

0
votes

Oui, les variables locales dans une fonction doivent être définitives. Quand j'arrive à ce problème, je définis simplement une variable factice dans la boucle for:

for (int i=0;i<10;i++) {
    int useI = i;
    JMenuItem item = new JMenuItem(new AbstractAction("Level-" + i) {
        @Override
        public void actionPerformed(ActionEvent e) {
            game.loadGame(useI);
            board.refresh();
            pack();
        }
    });
}


0 commentaires