Key Listener keeps listening for more keys, and i can't figure out how to stop it from doing so

259 Views Asked by At

So i made a little sudoku game where I've used toggle buttons to take input. Basically when a toggle button is toggled, a key listener is activated that listens for keys 1-9. Problem is, after the key is entered, i've used buttonGroup.clearSelection(), and it toggles the button again so it's deselected, but there's a small dotted rectangle over the text, and if i press any other digit, it changes the previous digit and writes the new one. I'm new to Java and GUIs so the problem could be something else entirely. Code is attached below. Please help!

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;


public class Test implements ActionListener, KeyListener {
    JFrame frame = new JFrame();
    JPanel panel = new JPanel();
    JToggleButton[] cells = new JToggleButton[81];
    JToggleButton selectedButton = new JToggleButton();
    ButtonGroup group = new ButtonGroup();
    int index;

    int[][] board = {
        {7, 2, 6, 4, 9, 3, 8, 0, 5},
        {3, 1, 5, 0, 2, 8, 0, 4, 6},
        {4, 0, 9, 6, 5, 1, 2, 3, 7},
        {8, 5, 2, 1, 0, 7, 6, 0, 3},
        {6, 7, 3, 9, 0, 5, 0, 2, 4},
        {9, 4, 0, 3, 6, 2, 7, 5, 8},
        {1, 9, 4, 8, 3, 6, 5, 0, 2},
        {5, 0, 7, 2, 1, 0, 3, 8, 9},
        {2, 3, 8, 5, 7, 9, 4, 6, 0}
    };

    public Test() {
        for (int x=0; x<81; x++) {
            cells[x] = new JToggleButton();
            group.add(cells[x]);
            cells[x].putClientProperty("index", x);
            cells[x].addActionListener(this);
            panel.add(cells[x]);
        }

        panel.setLayout(new GridLayout(9, 9, 2, 2)); 
        panel.setBackground(Color.black);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

        printBoard(board);

        frame.setJMenuBar(menuBar);
        frame.pack();
        frame.add(panel); 
        frame.pack();
        frame.setSize(600, 600);
        frame.setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
        selectedButton = (JToggleButton)e.getSource();
        index = (int) selectedButton.getClientProperty("index");
        selectedButton.addKeyListener(this);
    }

    public void keyPressed(KeyEvent e) {
        Integer digit;
        Integer r, c;
        r = index / 9;
        c = index % 9;
        digit = Integer.valueOf(e.getKeyCode() - 48);       

        if (digit > 0 && digit <10) {
            board[r][c] = digit;
        }

        String s = digit.toString();

        if (e.getKeyCode() >= 49 && e.getKeyCode() <= 57) {
            selectedButton.setText(s);
            group.clearSelection();
        } else if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE || e.getKeyCode() == KeyEvent.VK_DELETE || e.getKeyCode() == KeyEvent.VK_ESCAPE) {
            board[r][c] = 0;
            selectedButton.setText("");
            group.clearSelection();
        } 
    }

    public void keyReleased(KeyEvent e) {
        group.clearSelection();
    }

    public void keyTyped(KeyEvent e) {}

    public void printBoard(int[][] board) {
        for (int x=0; x<81; x++) { 
            cells[x].setEnabled(true);
        }
        Integer digit;
        String buttonText;

        int buttonIndex = 0;
        for (int r=0; r<9; r++) {
            for (int c=0; c<9; c++) {
                digit = Integer.valueOf(board[r][c]);
                if (digit == 0) {
                    cells[buttonIndex].setText("");
                    buttonIndex++;
                    continue;
                }
                else if (digit != 0) {
                    buttonText = digit.toString();
                    cells[buttonIndex].setText(s);
                    cells[buttonIndex].setEnabled(false);
                    buttonIndex++;
                }
            }
        }
    }

    public static void main(String[] args) {
        new Test();
    }
}    

group here is a ButtonGroup of all the toggle buttons. It does deselect the button but key listener still stays activated. Please help.

1

There are 1 best solutions below

1
Gilbert Le Blanc On

All you have to do is remove the key listener when the key is released.

I had to comment out the JMenu because it must be somewhere else,

Here's the GUI.

Sudoku Test GUI

And here's the code I used.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class SudokuTest implements ActionListener, KeyListener {
    JFrame frame = new JFrame("Sudoku Test");

    JPanel panel = new JPanel();
    JToggleButton[] cells = new JToggleButton[81];
    JToggleButton selectedButton = new JToggleButton();
    ButtonGroup group = new ButtonGroup();
    int index;

    int[][] board = { { 7, 2, 6, 4, 9, 3, 8, 0, 5 }, { 3, 1, 5, 0, 2, 8, 0, 4, 6 }, { 4, 0, 9, 6, 5, 1, 2, 3, 7 },
            { 8, 5, 2, 1, 0, 7, 6, 0, 3 }, { 6, 7, 3, 9, 0, 5, 0, 2, 4 }, { 9, 4, 0, 3, 6, 2, 7, 5, 8 },
            { 1, 9, 4, 8, 3, 6, 5, 0, 2 }, { 5, 0, 7, 2, 1, 0, 3, 8, 9 }, { 2, 3, 8, 5, 7, 9, 4, 6, 0 } };

    public SudokuTest() {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Font font = panel.getFont().deriveFont(32F).deriveFont(Font.BOLD);
        for (int x = 0; x < 81; x++) {
            cells[x] = new JToggleButton();
            group.add(cells[x]);
            cells[x].putClientProperty("index", x);
            cells[x].addActionListener(this);
            cells[x].setFont(font);
            panel.add(cells[x]);
        }

        panel.setLayout(new GridLayout(9, 9, 2, 2));
        panel.setBackground(Color.black);

        printBoard(board);

//        frame.setJMenuBar(menuBar);
        frame.add(panel);
        frame.pack();
        frame.setSize(600, 600);
        frame.setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
        selectedButton = (JToggleButton) e.getSource();
        index = (int) selectedButton.getClientProperty("index");
        selectedButton.addKeyListener(this);
    }

    public void keyPressed(KeyEvent e) {
        Integer digit;
        Integer r, c;
        r = index / 9;
        c = index % 9;
        digit = Integer.valueOf(e.getKeyCode() - 48);

        if (digit > 0 && digit < 10) {
            board[r][c] = digit;
        }

        String s = digit.toString();

        if (e.getKeyCode() >= 49 && e.getKeyCode() <= 57) {
            selectedButton.setText(s);
            group.clearSelection();
        } else if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE || e.getKeyCode() == KeyEvent.VK_DELETE
                || e.getKeyCode() == KeyEvent.VK_ESCAPE) {
            board[r][c] = 0;
            selectedButton.setText("");
            group.clearSelection();
        }
    }

    public void keyReleased(KeyEvent e) {
        group.clearSelection();
        selectedButton.removeKeyListener(this);
    }

    public void keyTyped(KeyEvent e) {
    }

    public void printBoard(int[][] board) {
        for (int x = 0; x < 81; x++) {
            cells[x].setEnabled(true);
        }
        Integer digit;
        String buttonText;

        int buttonIndex = 0;
        for (int r = 0; r < 9; r++) {
            for (int c = 0; c < 9; c++) {
                digit = Integer.valueOf(board[r][c]);
                if (digit == 0) {
                    cells[buttonIndex].setText("");
                    buttonIndex++;
                } else {
                    buttonText = digit.toString();
                    cells[buttonIndex].setText(buttonText);
                    cells[buttonIndex].setEnabled(false);
                    buttonIndex++;
                }
            }
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new SudokuTest();
            }
        });
    }

}