How to pass a local variable to an anonymous class?

Asked

Viewed 237 times

1

I need to pass the control variable of a for, as a parameter for a method. The problem, is that I am trying to do this according to the JRadioButton which was selected, I am creating them according to my for, and set events for them then.

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

(Remark: on the if, in e.getActionCommand().equals(tituloColuna[i]) is an attempt to have the action applied only to the 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.
    }
}
  • Why not turn the variable into a class field?

  • @diegofm as well ?

  • I do not understand anything that is being done in this loop. Can you explain better? It has an array of columns that is never related to a table, which is also never used in code.

  • @diegofm can do it! Come on, so the for will be done as long as it’s smaller than the numeroColunas, which I’m picking up from the table. Then I create the radios according to this amount of columns, and finally I name the columns for them with the Colon title, in this example it is not clear the usefulness of the array with the names, but it is because I did not find it necessary to add them dynamically there, nor the table, that I just put to pick up the columns.

  • But then you generate an interpretation problem of what the code will actually do, and it becomes complicated to suggest some way even related to the swing, which is easier or better maybe than the one you’re doing.

  • Do you actually create an array for column names in your application? If the answer is no, you can do otherwise there.

  • @diegofm yes I create, and added at another time. Oh he is taking the array just to give the name of the radios.

  • The code isn’t making much sense to me. In the same iteration, you add an actioncommand on the radiobutton and then do an if to check if it’s himself, it doesn’t make sense that.

  • Is that I needed to try to do something not to run the other radios together, but if you have any suggestions I can try to change.

  • But why do you define an actioncommand and then check if it is itself inside the same radio that just defined it? Do you realize the redundancy of your code? This if is completely unnecessary.

  • @diegofm really, confirmed this now, it’s not even necessary. Now I need to resolve the variable within the event

Show 6 more comments

1 answer

3


There are two ways to solve this scope problem: either you find a way to pass a final local variable to the anonymous class or you increase the scope of the variable at class level. I think the second option is not so useful, since you will apparently only use this variable to iterate the loop and nothing else.

It is also possible to circumvent this by creating a class that extends the Listener you want to apply, passing the value to this new class, but I believe that it is also not necessary to increase the complexity to this level according to the given example.

Then we can solve with the first form, which is to create a way to pass the loop iteration index to the anonymous class, so that the iteration can be incremented and the loop iteration variable does not need to be final. To do this, just make a copy of the current index inside the loop and pass this copy to the anonymous class, because it can 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());
    });
}

Thus, changes to your code are minimal, solving the scope problem.

Within the example given in the question, this is the least laborious suggestion and that will least change your code.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.