Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom Java Mouse Listeners?

First off, I came to Java as a website programmer. In JavaScript, all you have to do to add a mousemove, mouseover, or click event is call an addEventListener function. From my limited experience with Java, you can't just implement the MouseListener interface from any object.

Basically, what I have so far is a JPanel, that paints some shapes (a CustomShape object with a paint method) that have x/y/width/height values. I want to add some type of mouse listener to the shape object, so that I can fire move/roll/click events for the shape. Just implementing the MouseListener interface to the CustomShape object doesn't work (for what I suppose are obvious reasons). I've looked up how to design custom event listeners, but it doesn't seem as though making a custom mouse listener is possible.

I eventually resorted to adding the mouse listener to the JPanel, and then looping through all the shape objects. If the shape object had a 'listener' attached, and the mouse coordinates verified the mouse event had occurred, it fired the method. Initially, it was fine, but as the application got more developed, it started getting really really messy. Plus, I would never be able to copy over the shape objects/interfaces to another application without copying a bunch of code.

As a simple illustration: (the actual code is quite large)

Interface CustomShape{
    int width, height, x, y;
    void paint(Graphics g);
}

public class StarShape implements CustomShape{
    int width, height, x, y;
    public StarShape(){
        width = 100;
        height = 100;
        x = 50;
        y = 50;
    }
    void paint(Graphics g){
        g.setColor(Color.black);
        g.draw(new Rectangle(x,y,width,height));
    }
}

public class Main extends JPanel{
    StarShape check = new StarShape();
    public Main(){  }
    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        check.paint(g);
    }
}

So, I was wondering if there is a clean way of implementing some type of mouse listener for a 'hand-drawn' shape.

like image 738
Azmisov Avatar asked Nov 04 '10 00:11

Azmisov


2 Answers

To be able to receive events, your "Shape" objects should extend java.awt.Component (or javax.swing.JComponent). Then you can add them to the JPanel as a child, and they'll receive events and you can add listeners directly to them.

The way you're doing, you have to manually track the position of your shapes in the JPanel. You'd add the mouse listener to the panel itself, and depending on the the x/y coordinates of the event you get, call some method on the shape to handle the event. Which is pretty much reimplementing what the base AWT/Swing classes will do for you.

like image 156
vanza Avatar answered Sep 22 '22 19:09

vanza


My approach to doing what you're trying to do. Compile, run, read :-)

(Note: you can copy every single line of code below into a single file Example01.java. Compile it and run it.)

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

public class Example01 {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame jf = new JFrame();
                MainPanel mainPanel = new MainPanel();
                jf.add(mainPanel);
                jf.setSize(640, 480);
                jf.setLocationRelativeTo(null);
                jf.setVisible(true);
            }
        });
    }
}

class MainPanel extends JPanel {
    StarShape check1 = new StarShape();
    StarShape check2 = new StarShape();

    public MainPanel() {
        check1.setName("check1");
        check2.setName("check2");
        check1.addMouseListener(new MyMouseListener(check1));
        check2.addMouseListener(new MyMouseListener(check2));
        this.add(check1);
        this.add(check2);
    }
}

class StarShape extends JComponent {
    public StarShape() {
        this.setPreferredSize(new Dimension(100, 100));
    }

    @Override
    protected void paintComponent(Graphics g) {
        g.setColor(Color.black);
        Graphics2D g2d = (Graphics2D) g;
        int x = 0;
        int y = 0;
        int width = this.getWidth() - 1;
        int height = this.getHeight() - 1;
        g2d.draw(new Rectangle(x, y, width, height));
    }
}

class MyMouseListener implements MouseListener {
    private final JComponent component;

    public MyMouseListener(JComponent component) {
        this.component = component;
    }

    public void mouseClicked(MouseEvent e) {
        System.out.println("mouseClicked: " + component.getName());
    }

    public void mouseEntered(MouseEvent e) {
        System.out.println("mouseEntered: " + component.getName());
        Dimension preferredSize = component.getPreferredSize();
        preferredSize.height += 20;
        preferredSize.width += 20;
        component.setPreferredSize(preferredSize);
        component.invalidate();
        SwingUtilities.getWindowAncestor(component).validate();
    }

    public void mouseExited(MouseEvent e) {
        System.out.println("mouseExited: " + component.getName());
        Dimension preferredSize = component.getPreferredSize();
        preferredSize.height -= 20;
        preferredSize.width -= 20;
        component.setPreferredSize(preferredSize);
        component.invalidate();
        SwingUtilities.getWindowAncestor(component).validate();
    }

    public void mousePressed(MouseEvent e) {
        System.out.println("mousePressed: " + component.getName());
    }

    public void mouseReleased(MouseEvent e) {
        System.out.println("mouseReleased: " + component.getName());
    }
}
like image 28
Mike Clark Avatar answered Sep 24 '22 19:09

Mike Clark