tags:

views:

21

answers:

1

My gaol is to draw several images using 2D graphics in a paintComponent() method. However, I'm not sure how I could add a MouseListener such that each image would know if it was selected.

My solution thus far is too simply record the coordinates of the mouse click, and see if they are contained within the boundaries of each of the images. However this will be difficult with images that have more complex boundaries.

Another option would be too create simple shapes and place them over the images, but again images with more complex boundaries will be difficult. In another discussion on SO found here, someone mentioned using GeneralPath to draw more complex shapes. I have never played with is, but this seems encouraging.

Of these 2 options, what seems to be the best solution, or are there other recommendations

+1  A: 

Are you images painted on top of one another or are they drawn separately.

If they are drawn separately, then you should do the custom painting on a JComponent. Then you can do the drawing by using the GeneralPath. You will also need to implement the contains(...) method by checking if the mouseclick is contained in the GeneralPath. If the contains() method is implemented properly then the MouseListener will respond properly.

Here is a simpler example:

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

public class RoundButton extends JButton {
    public RoundButton(String label) {
        super(label);

        // These statements enlarge the button so that it
        // becomes a circle rather than an oval.
        Dimension size = getPreferredSize();
        size.width = size.height = Math.max(size.width, size.height);
        setPreferredSize(size);

        // This call causes the JButton not to paint the background.
        // This allows us to paint a round background.
        setContentAreaFilled(false);
    }

    // Paint the round background and label.
    protected void paintComponent(Graphics g) {
    if (getModel().isArmed()) {
            // You might want to make the highlight color
            // a property of the RoundButton class.
            g.setColor(Color.lightGray);
        } else {
            g.setColor(getBackground());
        }
    g.fillOval(0, 0, getSize().width-1, getSize().height-1);

        // This call will paint the label and the focus rectangle.
    super.paintComponent(g);
    }

    // Paint the border of the button using a simple stroke.
    protected void paintBorder(Graphics g) {
        g.setColor(getForeground());
        g.drawOval(0, 0, getSize().width-1, getSize().height-1);
    }

    // Hit detection.
    Shape shape;
    public boolean contains(int x, int y) {
        // If the button has changed size, make a new shape object.
        if (shape == null || !shape.getBounds().equals(getBounds())) {
            shape = new Ellipse2D.Float(0, 0, getWidth(), getHeight());
        }
        return shape.contains(x, y);
    }

    // Test routine.
    public static void main(String[] args) {
        // Create a button with the label "Jackpot".
        JButton button = new RoundButton("Jackpot");
        button.setBackground(Color.green);
        button.setBounds(0, 0, 100, 100);

        JButton button2 = new RoundButton("Jackpot2");
        button2.setBackground(Color.red);
        button2.setBounds(50, 50, 100, 100);

        // Create a frame in which to show the button.
        JFrame frame = new JFrame();
        frame.getContentPane().setBackground(Color.yellow);
        frame.getContentPane().setLayout(null);
        frame.getContentPane().add(button);
        frame.getContentPane().add(button2);
//        frame.getContentPane().setLayout(new FlowLayout());
        frame.setSize(200, 200);
        frame.setVisible(true);

        MouseListener mouseListener = new MouseAdapter() {
            public void mouseEntered( MouseEvent e )
            {}

            public void mouseExited( MouseEvent e )
            {}

            public void mouseClicked( MouseEvent e )
            {
                System.out.println( "clicked " );
            }

            public void mousePressed( MouseEvent e )
            {
                System.out.println( "pressed " );
            }

            public void mouseReleased( MouseEvent e )
            {
                System.out.println( "released " );
            }
        };
        button.addMouseListener( mouseListener );

    }
}
camickr
This looks like it should work. In regards to your question of whether I am painting images on top of each other... I was hoping to have roughly 7-8 images painted within one paintComponent() method. This would then need 7-8 contains() methods as well. Couldn't I just have separate classes each with its own shape to achieve this instead of separating the images themselves? Thanks.
Koop
You should have separate components so each can have its own shape. Then you just add these "shape components" to a panel the same way you do with any other Swing component. It will be easier to work with if the components are not layered. However, the components can be layered, but remember only the component on the top will receive the mouse event, based on the ZOrder of the component.
camickr