Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Swing adding mouse Listener (inner class) for an array of buttons leads to malfunction

Ok, so the program I want to build is simple. There are five buttons named from 0 to 4. If any of the buttons are pressed, then the number 0 to 4 is printed in console.

enter image description here

I have used a GridLayout to place the buttons in the frame. And to set up each button I have created a method, inicializarIG().

This inicializarIG() method creates an array of 5 buttons and inside a for loop it does:

  • Create an instance of a button for each cell in the array of buttons.
  • Set up a mouseListener for each button. The value to print in each Listener is different, it is determined by the index of the loop (AND I WANT TO DO IT BY USING THE INDEX!).
  • Add The button to the main frame.

Surprisingly, This simple program doesn´t work properly. It always print the number "5" no matter what button is pressed:

enter image description here

NOTE: I had to put the index var outside the inicializarIG() method in order to fulfill the var scope for the Listeners. I don't know if the problem is related, just saying in cause it might help.

THE CODE:

import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JButton;
import javax.swing.JFrame;


public class IGrafica {

    private JFrame frame;
    public int index=0;



    public IGrafica(){
        frame = new JFrame();
        configureFrame();
        inicializarIG();

    }

    public void configureFrame(){
        frame.setBounds(100,100,400,400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(new GridLayout(1,5)); //
    }


    public void inicializarIG(){

        //Buttons

        JButton [] botones = new JButton [5];

        //Loop to set up buttons and add the mouseListener
        for (index = 0; index < botones.length; index++) {
            botones[index] = new JButton(Integer.toString(index));


            //Set up each listener 
            botones[index].addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    System.out.println(index);
                    //texto.setBackground(colores[index]);
                }           
            });

            //Add the button
            frame.getContentPane().add(botones[index]);

        }       
    }



    public void visualizate(){
        frame.setVisible(true);
    }



    public static void main(String[] args) {        
        IGrafica window = new IGrafica();
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                window.visualizate();
            }
        });

    }
}

Thank you in advance. Any idea will be welcomed.

Jesús

like image 864
Jesus Avatar asked Oct 01 '15 23:10

Jesus


1 Answers

First of all, don't use a MouseListener for this, but rather use an ActionListener, since this works best for buttons. Next of all, you need to remember that your listener is a class of its own, and it needs a variable of its own to store its own index, else it uses the final value of the loop index which is not what you want. Either this or use the ActionEvent's actionCommand property, a value which will match the text of the button. So:

botones[index].addActionListener(new MyActionListener(index));

and

// a private inner class
private class MyActionListener implements ActionListener {
    private int index;

    public MyActionListener(int index) {
        this.index = index;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("index is: " + index);
        System.out.println("Action Command is: " + e.getActionCommand());
    }
}

Or if you want to use an anonymous inner class:

        botones[index].addActionListener(new ActionListener() {
            private int myIndex;

            {
                this.myIndex = index;
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("index is: " + myIndex);
            }
        });
like image 171
Hovercraft Full Of Eels Avatar answered Sep 22 '22 15:09

Hovercraft Full Of Eels