user7202454
user7202454

Reputation:

MouseClicked listener not working with gui

I created this program which gets the mouse coordinates and now I want to add a mouseClicked which creates a rectangle at certain coordinates when the mouse is pressed. But it does not work. Here is my code:

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


@SuppressWarnings("serial")
public class GameSetup extends JPanel implements MouseMotionListener {

public static JFrame njf = new JFrame("Test");
public static int x = 0, y = 0;
public static boolean c = false;
public static void main(String[] args) {

    GameSetup gs = new GameSetup();
    gs.addMouseMotionListener(gs);
    njf.add(gs);
    njf.setVisible(true);

}

public void paintComponent(Graphics g) {
    super.paintComponent(g);

    this.setBackground(Color.BLACK);

    g.setColor(Color.GREEN);
    g.drawRect(150, 75, 200, 100);
    g.setColor(Color.ORANGE);
    g.drawString("Play", 239, 123);


    if (x > 150 && y > 75 && x < 350 && y < 175){
        g.drawRect(150, 75, 200, 100);
    } 
    if(x > 150 && y > 75 && x < 350 && y < 175 && c){
        g.fillRect(10 , 10 ,100 ,100);
    }
}

public GameSetup() {

    super();
    setSize(500, 500);
    njf.setSize(500,500);
    njf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    njf.setResizable(false);
    njf.setLocationRelativeTo(null);

}

@Override
public void mouseDragged(MouseEvent arg0) {

}

@Override
public void mouseMoved(MouseEvent e) {
    x = e.getX();
    y = e.getY();
    if (x > 0 && y > 0) repaint(); else repaint();
}
public void mouseClicked(MouseEvent ea){
    c = true;
}
}

How can I make this work? Thanks

Upvotes: 0

Views: 581

Answers (2)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285403

You can't put an @Override over mouseClicked(...) can you? And that's because your class does not implement the proper interface: MouseListener. Implement this interface as well, add the object also as a MouseListener, and you'll have access to MouseListener events. Also consider placing repaint() calls with your listener methods so that the GUI repaints itself when necessary.

My own preference is not to have my view classes also implement my listenener interfaces, so if this were my program, I'd create an inner class that extends MouseAdapter and use that as both a MouseListener and MouseMotionListener.

Other issues:

  • Don't call setBackground within a painting method. Instead call it in the constructor.
  • Avoid "magic" numbers if possible.
  • Consider using a JLabel or JButton to do this work, as you're usually better off using a higher level construct for ease of debugging and enhancement.

For example without JLabel...

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.*;


@SuppressWarnings("serial")
public class GameSetup2 extends JPanel {
    private static final int PREF_W = 500;
    private static final int PREF_H = PREF_W;
    private static final Color BG = Color.BLACK;
    private static final Color PASSIVE_COLOR = Color.GREEN;
    private static final Color ACTIVE_COLOR = Color.ORANGE;
    private static final String PLAY = "Play";
    private static final int PLAY_X = 239;
    private static final int PLAY_Y = 123;
    private Rectangle rectangle = new Rectangle(150, 75, 200, 100);
    private Color rectColor = PASSIVE_COLOR;
    private Color playColor = PASSIVE_COLOR;

    public GameSetup2() {
        setBackground(BG);
        MyMouse myMouse = new MyMouse();
        addMouseListener(myMouse);
        addMouseMotionListener(myMouse);
        // TODO Auto-generated constructor stub
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setColor(playColor);
        g2.drawString(PLAY, PLAY_X, PLAY_Y);
        g2.setColor(rectColor);
        g2.draw(rectangle);
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }

    private class MyMouse extends MouseAdapter {
        @Override
        public void mouseMoved(MouseEvent e) {
            if (rectangle.contains(e.getPoint())) {
                rectColor = ACTIVE_COLOR;
            } else {
                rectColor = PASSIVE_COLOR;
            }
            repaint();
        }

        @Override
        public void mousePressed(MouseEvent e) {
            if (rectangle.contains(e.getPoint())) {
                playColor = ACTIVE_COLOR;
            } 
            repaint();
        }

        public void mouseReleased(MouseEvent e) {
            playColor = PASSIVE_COLOR;
            repaint();
        };
    }

    private static void createAndShowGui() {
        GameSetup2 mainPanel = new GameSetup2();

        JFrame frame = new JFrame("GameSetup2");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

Upvotes: 1

charego
charego

Reputation: 137

To go with what Hovercraft Full Of Eels said, I refactored a bit. Notice:

  • Implement MouseListener or extend MouseAdapter, and register the listener (addMouseListener)
  • Variables don't need to be public or static -- try to minimize scope, use more encapsulation as a best practice
  • Add repaint() call to mouseClicked
  • Change c to clicked and made it toggle between true and false, so you can see it change

Try this:

public class Game {

    public static void main(String[] args) {

        final JFrame frame = new JFrame("Test");
        frame.setSize(500, 500);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.add(new GamePanel());
        frame.setVisible(true);

    }

    @SuppressWarnings("serial")
    private static class GamePanel extends JPanel {

        private int x = 0;
        private int y = 0;
        private boolean clicked = false;

        public GamePanel() {
            super();
            setSize(500, 500);
            setBackground(Color.BLACK);
            addMouseListener(new MouseListenerImpl());
            addMouseMotionListener(new MouseMotionListenerImpl());
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);

            g.setColor(Color.GREEN);
            g.drawRect(150, 75, 200, 100);
            g.setColor(Color.ORANGE);
            g.drawString("Play", 239, 123);

            if (x > 150 && y > 75 && x < 350 && y < 175) {
                g.drawRect(150, 75, 200, 100);
                if (clicked) {
                    g.fillRect(10, 10, 100, 100);
                }
            }
        }

        private class MouseListenerImpl extends MouseAdapter {
            @Override
            public void mouseClicked(MouseEvent e) {
                clicked = !clicked;
                repaint();
            }
        }

        private class MouseMotionListenerImpl extends MouseMotionAdapter {
            @Override
            public void mouseMoved(MouseEvent e) {
                x = e.getX();
                y = e.getY();
                repaint();
            }
        }
    }
}

Upvotes: 1

Related Questions