Lets start with the MouseMotionListener class. It is an inner class for the public class ClassSDK extends JPanel {} class.
private class MouseTracker implements MouseMotionListener {
public void mouseDragged(MouseEvent e) {/*do nothing*/
}
public void mouseMoved(MouseEvent e) {
//check if mouse is over the sudoku table
if (e.getX() > inset && e.getX() < (inset + (9 * squareWidth))
//mouse in horizontal range; check vertical
&& e.getY() > inset && e.getY() < (inset + (9 * squareWidth))) {
//in sudoku table...
//convert mouse coordinates to cell coordinates
mouseCol = (e.getX() - inset) / squareWidth;
mouseRow = (e.getY() - inset) / squareWidth;
highlightCell(mouseRow, mouseCol, gBack, Color.ORANGE);
} else {
//set mouseCol and mouseRow to -1 identifying mouse is out of table
mouseRow = -1;
mouseCol = -1;
//clear the backImg highlight effect
highlightCell(0, 0, gBack, null);
}
}
}
So in this class I am tracking the mouse over the JPanel in which I have drawn the sudoku table. Once the mouse pointer is above the sudoku table (insets is a variable that contains the size of my empty border around the table) I start converting the coordinates of the pointer to coordinates of a cell in the sudoku table. In case you don't know, a sudoku table consists of 9 rows and 9 columns. highlightCell() is a method which can either paint a specified cell in certain colour, or clear it from the colour. I will not describe how it works now though. It will be a part of my BufferedImages use blog. You will see where I initialize and add this listener to the ClassSDK JPanel in my MouseListener class:
private class ClickListen implements MouseListener {
public void mouseClicked(MouseEvent e) {/*do nothing*/
}
public void mousePressed(MouseEvent e) {/*do nothing*/
}
public void mouseReleased(MouseEvent e) {
//check if click was inside the sudoku
if (mouseRow == -1 || mouseCol == -1) {
return; //click outside sudoku table
}
/*check if there is an entry process already initiated (flag -1 on lockRow and lockCol means no entry process)*/
if (lockRow != -1 || lockCol != -1) {
//if so unload the input listener for that process
KeyListener[] l = getKeyListeners();
if (l.length > 0) { //if there was a key listener which should be the case
removeKeyListener(l[0]); //remove it
System.out.println("Removed previous input listener.");
}
}
//ready to start input method
createSDK();
}
public void mouseClicked(MouseEvent e) {/*do nothing*/
}
public void mousePressed(MouseEvent e) {/*do nothing*/
}
public void mouseReleased(MouseEvent e) {
//check if click was inside the sudoku
if (mouseRow == -1 || mouseCol == -1) {
return; //click outside sudoku table
}
/*check if there is an entry process already initiated (flag -1 on lockRow and lockCol means no entry process)*/
if (lockRow != -1 || lockCol != -1) {
//if so unload the input listener for that process
KeyListener[] l = getKeyListeners();
if (l.length > 0) { //if there was a key listener which should be the case
removeKeyListener(l[0]); //remove it
System.out.println("Removed previous input listener.");
}
}
//ready to start input method
createSDK();
}
public void mouseEntered(MouseEvent e) {
//start tracking the mouse once entered in the component
addMouseMotionListener(new MouseTracker());
requestFocus(); //automatically focust the panel with the mouse over it
}
public void mouseExited(MouseEvent e) {
//remove motion listener if mouse is out of panel to save ressources
MouseMotionListener[] l = getMouseMotionListeners();
removeMouseMotionListener(l[0]);
}
}
The createSDK() method is a method which controls the input together with my KeyListener class. The part where I check the variables lockRow and lockCol for a flag of -1 is that, if the user clicks on a cell and starts the entry process but does not enter a value and clicks on another cell instead, the keylistener that listens for entry in the previous cell has to be removed, else with one click of a button the value would be entered in both cells. lockRow and lockCol save the coordinates of the cell where the click occurred until the point when a value is entered and the entry process finishes, when they switch value back to -1.
/**
* Called by createSDK, this class waits for a digit to be entered and then
* saves it to the mainG array, paints it on the grid.
*/
private class InputListen implements KeyListener {
public void keyTyped(KeyEvent e) {
System.out.println("key typed");
if (lockRow == -1 || lockCol == -1) //there is no lock on any cell
{
return;
}
char input = e.getKeyChar();
//check if input is a digit
if (Character.isDigit(input)) {
//save input to sudoku array and
//show input on the sudoku table
addDigitToMainG(lockRow, lockCol, Integer.parseInt(Character.toString(input)));
//clear visual highlight of cell and reset lock variables
lockCol = -1;
lockRow = -1;
highlightCell(0, 0, gLock, null);
//remove the key listener
KeyListener[] l = getKeyListeners();
removeKeyListener(l[0]);
}
}
public void keyPressed(KeyEvent e) {/*do nothing*/
}
public void keyReleased(KeyEvent e) {/*do nothing*/
}
}
* Called by createSDK, this class waits for a digit to be entered and then
* saves it to the mainG array, paints it on the grid.
*/
private class InputListen implements KeyListener {
public void keyTyped(KeyEvent e) {
System.out.println("key typed");
if (lockRow == -1 || lockCol == -1) //there is no lock on any cell
{
return;
}
char input = e.getKeyChar();
//check if input is a digit
if (Character.isDigit(input)) {
//save input to sudoku array and
//show input on the sudoku table
addDigitToMainG(lockRow, lockCol, Integer.parseInt(Character.toString(input)));
//clear visual highlight of cell and reset lock variables
lockCol = -1;
lockRow = -1;
highlightCell(0, 0, gLock, null);
//remove the key listener
KeyListener[] l = getKeyListeners();
removeKeyListener(l[0]);
}
}
public void keyPressed(KeyEvent e) {/*do nothing*/
}
public void keyReleased(KeyEvent e) {/*do nothing*/
}
}
This is how the key listener works. It unloads itself once the process has finished. addDigitToMainG(int,int,int) is a method that adds a number to specific row and column in my array and then prints it on the screen as well.
It's a lot of code and explanation and I try to be detailed in my comments, so if you have any questions please comment. This is a good exercise on event driven programming combining 3 different types of listeners.
No comments:
Post a Comment