Home > OS >  JOptionPane behaving weird with KeyListener
JOptionPane behaving weird with KeyListener

Time:08-13

I am currently working on a Sudoku solver with a GUI. Neither is finished, but the GUI is partly operational. However I have encountered something weird. The code follows below:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class SudokuWindow extends JFrame {
    public SudokuWindow() {
        SwingUtilities.invokeLater(()->createSudokoWindow());
    }
    
    private void createSudokoWindow() {
        JFrame frame = new JFrame("Sudoku!");
        int height = 600;
        int width = 1000;
        frame.setPreferredSize(new Dimension(width,height));
        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new FlowLayout());
        SudokuBoard sB= new SudokuBoard(width/2,width/2,9,9);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton button1 = new JButton("Import solvabel setup");
        JButton button2 = new JButton("Find solution");
        JTextField t1=new JTextField("0");  
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
        panel.add(button1);
        panel.add(button2);
        panel.add(t1);
        mainPanel.add(sB,BorderLayout.WEST);
        mainPanel.add(panel, BorderLayout.EAST);
        frame.add(mainPanel);
        frame.pack();
        frame.setVisible(true);
    }
    
    public static void main(String[] args) {
        new SudokuWindow();
    }
}

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFormattedTextField;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class SudokuBoard extends JPanel {
      int width, height, rows, cols;
      JFormattedTextField[][] txtM = new JFormattedTextField[9][9];
      
      SudokuBoard(int w, int h, int r, int c) {
            setSize(width = w, height = h);
            this.setPreferredSize(new Dimension(w,h));
            for(int i = 0; i < r; i  ) {
                for(int j = 0; j < c; j  ) {
                    txtM[i][j] = new JFormattedTextField();
                }
            }
            rows = r;
            cols = c;
      }
      
      public void paint(Graphics g) {
            width = getSize().width;
            height = getSize().height;
            
            int rowHt = height / rows;
            int colWt = width / cols;
            JFormattedTextField t;
            
            for (int i = 0; i < rows; i  ) {
                for(int j = 0; j < cols; j  ) {
                    t = txtM[i][j];
                    t.setText("0");
                    t.setSize(rowHt,colWt);
                    t.setMargin(new Insets(0,18,0,0));
                    t.setFont(new Font("TimesRoman",Font.PLAIN,26));
                    t.setLocation(i*colWt, j*rowHt);
                    t.addKeyListener(keyListener);
                    if((((j 1) % 9 == 1 || (j 1) % 9 == 2 || (j 1) % 9 == 3) && ((i 1) % 9 == 1 || (i 1) % 9 == 2 || (i 1) % 9 == 3))){
                        t.setBackground(Color.MAGENTA);
                    } else if(((j 1) % 9 == 7 || (j 1) % 9 == 8 || (j 1) % 9 == 0) && ((i 1) % 9 == 1 || (i 1) % 9 == 2 || (i 1) % 9 == 3)){
                        t.setBackground(Color.MAGENTA);
                    } else if(((j 1) % 9 == 7 || (j 1) % 9 == 8 || (j 1) % 9 == 0) && ((i 1) % 9 == 7 || (i 1) % 9 == 8 || (i 1) % 9 == 0)){
                        t.setBackground(Color.MAGENTA);
                    } else if(((j 1) % 9 == 1 || (j 1) % 9 == 2 || (j 1) % 9 == 3) && ((i 1) % 9 == 7 || (i 1) % 9 == 8 || (i 1) % 9 == 0)){
                        t.setBackground(Color.MAGENTA);
                    } else if(((j 1) % 9 == 4 || (j 1) % 9 == 5 || (j 1) % 9 == 6) && ((i 1) % 9 == 4 || (i 1) % 9 == 5 || (i 1) % 9 == 6)){
                        t.setBackground(Color.MAGENTA);
                    }
                    add(t);
                }
            }
        }
        
        KeyListener keyListener = new KeyListener() {
            @Override
            public void keyPressed(KeyEvent e) {}

            @Override
            public void keyTyped(KeyEvent e) {
                if(Character.isLetter(e.getKeyChar()) || ((Character) e.getKeyChar()).equals('0')){
                    JOptionPane.showMessageDialog(null, "Invalid input!");
                }
                
            }
            
            @Override
            public void keyReleased(KeyEvent e) {}
        };
}

The code works as intended so far except for one thing. When the KeyListener finds a Letter or a 0, the JOptionPane pops up three times. This is kind of annoying, and I don't understand why it does that.

Also I am trying to reach the JFormattedTextFields so I can reset them after a Invalid input but can't reach them through the KeyListener. Is there some nice way to do this?

If anyone could help me figure this out I would greatly appreciate it!

Thank you!

CodePudding user response:

TL;DR
Your problem is that you are adding another KeyListener to each JFormattedTextField every time method paint is called and each listener is executed. So if...

the JOptionPane pops up three times

then it means that method paint was called three times which caused three listeners to be added to each JFormattedTextField.


Other general notes regarding your code:

Class SudokuWindow:

  1. Swing application classes, such as your SudokuWindow, don't need to extend JFrame. In any case you create a new JFrame in method createSudokoWindow() (of class SudokuWindow) so really no need for class SudokuWindow to extend JFrame.
  2. mainPanel.add(sB,BorderLayout.WEST); Because you explicitly set the screen capture

  • Related