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
:
- Swing application classes, such as your
SudokuWindow
, don't need to extendJFrame
. In any case you create a newJFrame
in methodcreateSudokoWindow()
(of classSudokuWindow
) so really no need for classSudokuWindow
to extendJFrame
. mainPanel.add(sB,BorderLayout.WEST);
Because you explicitly set the