'How to assign differents MouseListener to differents JTextField?

im trying to make a Sudoku game and I want to change the background color of the same box, same column and same row when I click on a JTextField. I'm trying to add multiple Mouse Listener, one for each JTextField but It doesnt work. I'm now testing changing the background color of just the JTextField that I click on.

The main problem is in here.

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class Panel extends JPanel {

    public static final int ROWS = 3;
    public static final int COLUMNS = 3;
    public static JTextField[][] fields = new JTextField[ROWS * COLUMNS][ROWS * COLUMNS];

    for (int i = 0; i < ROWS*COLUMNS; i++) {
        for (int j = 0; j < ROWS*COLUMNS; j++) {
            fields[i][j] = new JTextField();
            int finalI = i;
            int finalJ = j;
            fields[i][j].addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    fields[finalI][finalJ].setBackground(Color.BLUE);
                }
            });
        }
    }
} 

I have also try with this but it doesn't work.

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class Panel extends JPanel {

    public static final int ROWS = 3;
    public static final int COLUMNS = 3;
    public static JTextField[][] fields = new JTextField[ROWS * COLUMNS][ROWS * COLUMNS];

    for (int i = 0; i < ROWS*COLUMNS; i++) {
        for (int j = 0; j < ROWS*COLUMNS; j++) {
            fields[i][j] = new JTextField();
            addMouseActions(i, j);
        }
    }
   

    private void addMouseActions(int row, int col){
        fields[row][col].addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                fields[row][col].setBackground(Color.BLUE);
            }
        });

    }
} 

Here it's the full code that I have for the Panel class.

import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class Panel extends JPanel {

    static String[] levels = {"Easy", "Medium", "Hard"};
    public static final JComboBox<String> levelsBox = new JComboBox<>(levels);
    private final JButton playButton = new JButton("Play");
    private final JButton checkButton = new JButton("Check");
    private final JButton hintButton = new JButton("Hint");
    private final JButton solveButton = new JButton("Solve");
    private final JButton exitButton = new JButton("Exit");

    public static final int ROWS = 3;
    public static final int COLUMNS = 3;
    public static JTextField[][] fields = new JTextField[ROWS * COLUMNS][ROWS * COLUMNS];

    public Panel(JFrame frame) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {

                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLocation(600, 200);
                frame.setLayout(new BorderLayout());
                frame.add(new SudokuBoard());
                frame.add(new MenuPane(), BorderLayout.AFTER_LINE_ENDS);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }

    public class MenuPane extends JPanel {

        public MenuPane() {
            setBorder(new EmptyBorder(4, 4, 4, 4));
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 1;
            gbc.weightx = 0;
            gbc.fill = GridBagConstraints.HORIZONTAL;

            JLabel diff = new JLabel("Select the difficulty: ");
            diff.setFont(new Font("SansSerif",Font.BOLD,18));
            add(diff, gbc);
            gbc.gridx++;

            levelsBox.setFont(new Font("SansSerif",Font.BOLD,16));
            add(levelsBox,gbc);
            gbc.gridy++;


            playButton.setActionCommand("Play");
            add(playButton, gbc);
            gbc.gridy++;

            checkButton.setActionCommand("Check");
            checkButton.setEnabled(false);
            add(checkButton, gbc);
            gbc.gridy++;

            hintButton.setActionCommand("Hint");
            hintButton.setEnabled(false);
            add(hintButton, gbc);
            gbc.gridy++;


            solveButton.setActionCommand("Solve");
            solveButton.setEnabled(false);
            add(solveButton, gbc);
            gbc.gridy++;

            exitButton.setActionCommand("Exit");
            add(exitButton, gbc);
        }
    }

    public static class SudokuBoard extends JPanel {

        private SubBoard[] subBoards;

        public SudokuBoard() {
            setBorder(new EmptyBorder(30, 30, 30, 10));
            subBoards = new SubBoard[ROWS * COLUMNS];
            setLayout(new GridLayout(ROWS, COLUMNS));
            for (int row = 0; row < ROWS; row++) {
                for (int col = 0; col < COLUMNS; col++) {
                    int bigIndex = (row * COLUMNS) + col;
                    int index = (row * ROWS) + col;
                    SubBoard board = new SubBoard(bigIndex);
                    board.setBorder(new LineBorder(Color.GRAY, 3));
                    subBoards[index] = board;
                    add(board);
                }
            }
        }
    }

    public static class SubBoard extends JPanel {

        public SubBoard(int bigIndex) {
            setLayout(new GridLayout(ROWS, COLUMNS));
            for (int row = 0; row < ROWS; row++) {
                for (int col = 0; col < COLUMNS; col++) {
                    int index = (row * COLUMNS) + col;
                    JTextField field = new JTextField();
                    field.setPreferredSize(new Dimension(60, 60));
                    field.setHorizontalAlignment(JTextField.CENTER);
                    field.setFont(new Font("SansSerif", Font.BOLD, 25));
                    field.setDocument(new JTextFieldLimit(1));
                    //field.setEditable(false);
                    fields[bigIndex][index] = field;
                    add(field);
                }
            }
        }
    }

    public void addListeners(Controller controller) {
        playButton.addActionListener(controller);
        checkButton.addActionListener(controller);
        hintButton.addActionListener(controller);
        solveButton.addActionListener(controller);
        exitButton.addActionListener(controller);
        for (int i = 0; i < ROWS*COLUMNS; i++) {
            for (int j = 0; j < ROWS*COLUMNS; j++) {
                fields[i][j] = new JTextField();
                int finalI = i;
                int finalJ = j;
                fields[i][j].addMouseListener(new MouseAdapter() {
                    @Override
                    public void mousePressed(MouseEvent e) {
                        fields[finalI][finalJ].setBackground(Color.BLUE);
                    }
                });
            }
        }
    }

    public void enableButtons(boolean enabled){
        checkButton.setEnabled(enabled);
        hintButton.setEnabled(enabled);
        solveButton.setEnabled(enabled);
    }
}

And this is the Controller Class that I'm using for Actions Events.

import pkgClient.MyClient;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Objects;

public class Controller implements ActionListener {
    Panel panel;
    JFrame frame;

    public Controller(Panel panel, JFrame frame) {
        this.frame = frame;
        this.panel = panel;
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        if (e.getActionCommand().equalsIgnoreCase("Play")){
            String level = Panel.levelsBox.getItemAt(Panel.levelsBox.getSelectedIndex());
            if(Objects.equals(level, "Easy")){
                MyClient.out.println("easyMode");
            }else if(Objects.equals(level, "Medium")){
                MyClient.out.println("mediumMode");
            }else if (Objects.equals(level, "Hard")){
                MyClient.out.println("hardMode");
            }
            panel.enableButtons(true);
            Panel.fields[0][0].setBackground(Color.WHITE);

        } else if(e.getActionCommand().equalsIgnoreCase("Check")){
            System.out.println("Comprobar");
            MyClient.out.println("check");
            panel.enableButtons(false);

        }else if(e.getActionCommand().equalsIgnoreCase("Hint")){
            System.out.println("Pista");
            MyClient.out.println("hint");


        } else if(e.getActionCommand().equalsIgnoreCase("Solve")){
            System.out.println("Resolver");
            MyClient.out.println("solve");
            panel.enableButtons(false);


        } else if(e.getActionCommand().equalsIgnoreCase("Exit")) {
            frame.dispose();
            MyClient.out.println("exit");
        }else if(e.getActionCommand().equalsIgnoreCase("Text")) {
            System.out.println("hola");
            Panel.fields[0][0].setBackground(Color.BLACK);

        }else{
            System.err.println("Error: unexpected event");
        }
    }
}

Is there any way to set an unique Mouse Event to every single JTextField like I do with buttons and Actions in the Controller Class? Or how do I have to do it?

Thank you.



Solution 1:[1]

I finally could solve the problem, I just needed to use a FocusListener instead of a MouseListener. I can change the background color of a field int the FocusGained(FocusEvent event) method and each JTextField has an independent event. I can know which JTextField is being clicked with event.getComponent() inside of the FocusGained method.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Medicandy