How to pass a local variable to an anonymous class?

1

I need to pass the control variable from a for , as a parameter to a method. The problem, is that I'm trying to do this according to the JRadioButton that was selected, I'm creating them according to my for, and defined events for them then.

The issue is that within ActionEvent I can not use the for control variable, unless it is final, however, this is not possible, since it can change "size" according to the columns of a table.

(Note: in if , in e.getActionCommand().equals(tituloColuna[i]) is an attempt to make the action only apply to radioButton that has the same name that gives it condition.)

Does anyone have any suggestions?

I made a very simple example, just to illustrate the situation.

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

public class TesteFor extends JFrame {

    public static void main(String[] args) {
        EventQueue.invokeLater(()
                -> {
            TesteFor ts = new TesteFor();
            ts.setVisible(true);
        });
    }

    public TesteFor() {
        setTitle("Teste");
        add(componentesTela());
        setPreferredSize(new Dimension(375, 300));
        pack();
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    private JComponent componentesTela() {
        JPanel jp = new JPanel();

        String tituloColuna[] = {"Coluna 01", "Coluna 02"};

        //Tabela apenas para indicar de onde veio os valores, não estou adicionando ela no exemplo.
        JTable tabela = new JTable();
        tabela.setModel(new DefaultTableModel(
                new Object[][]{
                    {null, null, null},
                    {null, null, null},
                    {null, null, null}
                },
                new String[]{
                    "", ""
                }
        ));

        int numeroColunas = tabela.getColumnModel().getColumnCount();

        for (int i = 0; i < numeroColunas; i++) {
            JRadioButton radio = new JRadioButton("Ocultar " + tituloColuna[i]);
            jp.add(radio);
            radio.setActionCommand(tituloColuna[i]); //e.getActionCommand() vai retornar o nome do radio clicado

            radio.addActionListener((ActionEvent e)
                    -> {
                //ERRO
                /*if (e.getActionCommand().equals(tituloColuna[i])) {
                    alterarTabela(i);
                    System.out.println("Peguei a " + e.getActionCommand());
                }*/
            });
        }
        return jp;
    }

    private void alterarTabela(int indiceColuna) {
        //alterar colunas de acordo com o indice.
    }
}
    
asked by anonymous 08.07.2017 / 22:41

1 answer

3

There are two ways to resolve this scope problem: either you arrange a way to pass an end local variable to anonymous class or increase the scope of the variable at the class level. I think the second option is not so useful, since you're apparently only going to use this variable to iterate through the loop and nothing else.

You can also work around this by creating a class that extends the listener you want to apply, passing the value to this new class, but I do not think it's necessary to increase complexity at this level either, according to the given example. p>

Then we can solve with the first form, which is to create a way to pass the index of the iteration of the loop to the anonymous class, so that the iteration can be incremented and the iteration variable of the loop need not be final. To do this, just make a copy of the current index inside the loop and pass this copy to anonymous class, since it may be final, since we only care about its value until the end of the current iteration:

for (int i = 0; i < numeroColunas; i++) {
    JRadioButton radio = new JRadioButton("Ocultar " + tituloColuna[i]);
    jp.add(radio);
    radio.setActionCommand(tituloColuna[i]); //e.getActionCommand() vai retornar o nome do radio clicado
    final int currentIndex = i;
    radio.addActionListener(e -> {
            alterarTabela(currentIndex);
            System.out.println("Peguei a " + e.getActionCommand());
    });
}

In this way, changes to your code are minimal, solving the scope problem.

Within the example given in the question, this is the least labor-intensive suggestion that will change your code.

    
08.07.2017 / 23:25