Search code examples
javamouseeventmousemouselistenercustom-cursor

How to create a separate class for a custom cursor


I am trying to make a game as a personal project and would like a custom cursor that has two states; normal and clicked. How can I create a separate class for that and use it in the class that creates the window?

This is just for a learning experience and chance to create a custom cursor for a game. I've tried putting the code into the Window class and not having a separate class for the mouse. That worked, but it was messy and I would like to learn how to clean it up by separating the classes.

If you don't know if I have something in one of the codes or not, just assume that I don't. I'm fairly new to programming and don't know that much.

//This is the code that worked
public class Window extends JFrame {
    Cursor normal = Toolkit.getDefaultToolkit().createCustomCursor(Toolkit.getDefaultToolkit().getImage("Cursor.gif"), new Point(0, 0), "Gauntlet");
    Cursor clicked = Toolkit.getDefaultToolkit().createCustomCursor(Toolkit.getDefaultToolkit().getImage("Cursor_Clicked.gif"), new Point(0, 0), "Gauntlet_Clicked");
    class myMouseListener implements MouseListener {
        @Override
        public void mouseEntered(MouseEvent arg0) {
            setCursor(normal);
        }
        public void mouseExited(MouseEvent arg0) {
        }
        @Override
        public void mouseClicked(MouseEvent arg0) {
        }
        @Override
        public void mousePressed(MouseEvent arg0) {
            setCursor(clicked);
        }
        @Override
        public void mouseReleased(MouseEvent arg0) {
            setCursor(normal);
        }
    }
    myMouseListener mml = new myMouseListener();
    public Window() {
        super.setSize(1200, 1000);
        super.addMouseListener(mml);
        super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        super.setVisible(true);
    }
    public static void main(String[] args) {
        new Window();
    }
}
//This is the current code
public class Window extends JFrame {
    public Window() {
        super.setSize(1200, 1000);
        super.add(new Mouse());
        super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        super.setVisible(true);
    }
    public static void main(String[] args) {
        new Window();
    }
}
//This is the new class for the cursor that I'm having trouble with
public class Mouse extends JFrame {
    public Mouse() {
        super.setCursor(c);
    }
    Cursor normal = Toolkit.getDefaultToolkit().createCustomCursor(Toolkit.getDefaultToolkit().getImage("Cursor.gif"), new Point(0, 0), "Gauntlet");
    Cursor clicked = Toolkit.getDefaultToolkit().createCustomCursor(Toolkit.getDefaultToolkit().getImage("Cursor_Clicked.gif"), new Point(0, 0), "Gauntlet_Clicked");
    Cursor c;
    class myMouseListener implements MouseListener {
        @Override
        public void mouseEntered(MouseEvent arg0) {
            c = normal;
        }
        public void mouseExited(MouseEvent arg0) {
        }
        @Override
        public void mouseClicked(MouseEvent arg0) {
        }
        @Override
        public void mousePressed(MouseEvent arg0) {
            c = clicked;
        }
        @Override
        public void mouseReleased(MouseEvent arg0) {
            c = normal;
        }
    }
}

With the current code, I expected there to be my custom cursor that changed whenever I pressed down the left mouse, just like in the functional code. However, the mouse did not change at all. It was as if I hadn't even written any code.


Solution

    1. You forgot to add the myMouseListener to the Mouse object.
    2. I don't believe you can add a JFrame into another JFrame, you could make Mouse extend JPanel rather than JFrame.
    3. When you write c = normal or c = clicked I believe this changes the pointer that c has within the Mouse class, but does not update the superclass's cursor as that cursor is saved with a separate variable, which still points to the uninitialized c. To fix this you can simply call setCursor(normal) or setCursor(clicked)like this:
    public class Mouse extends JPanel {
        public Mouse() {
            this.addMouseListener(new myMouseListener());
        }
        Cursor normal = Toolkit.getDefaultToolkit().createCustomCursor(Toolkit.getDefaultToolkit().getImage("Cursor.gif"), new Point(0, 0), "Gauntlet");
        Cursor clicked = Toolkit.getDefaultToolkit().createCustomCursor(Toolkit.getDefaultToolkit().getImage("Cursor_Clicked.gif"), new Point(0, 0), "Gauntlet_Clicked");
        class myMouseListener implements MouseListener {
            @Override
            public void mouseEntered(MouseEvent arg0) {
                setCursor(normal);
            }
            public void mouseExited(MouseEvent arg0) {
            }
            @Override
            public void mouseClicked(MouseEvent arg0) {
            }
            @Override
            public void mousePressed(MouseEvent arg0) {
                setCursor(clicked);
            }
            @Override
            public void mouseReleased(MouseEvent arg0) {
                setCursor(normal);
            }
        }
    }