tags:

views:

111

answers:

3

I am working on an application that involves the user requiring to hover over several moving dots on the screen in order to launch specific popups. At the moment, i am listening for mouseMoved events on the JPanel onto which the dots are rendered, and then launching the required pop ups whenever the cursor is within a specific distance of a dot.

When i have hundreds of dots - this probably becomes quite expensive.

Wouldnt the ideal solution be to represent my 'dots' as small components and register a mouse listener with each dot?

Does anyone know how i might represent a small ellipse with a JComponent?

Many thanks

+1  A: 

You write "this probably becomes quite expensive"

Whether you code the "isMouseCloseToDot" method yourself, or whether you use something built into Swing, in either case the work still needs to be performed by the computer to find out whether a dot is activated.

I recommend sticking with your current approach unless you have determined that this approach is indeed too expensive. Do a small test with a couple of hundred dots. Is the response time acceptable?

Steve McLeod
It is acceptable. I have lots and lots of listening events to perform to a variety of objects on the panel. So, although i have assumed that the swing routines would be more efficient, i am also faced with a listener class with dozens of search loops everywhere and references to object lists that are rendered on the panel. For a code brevity point of view - this approach could offer benefits too.
TotalCruise
A: 

Not sure which approach is more expensive, but component based approach is definitely easier to implement.

All you have to do is to create your own component, override paint and contains methods. Add it to the specific position in the container (using absolute layout or any other depending on your needs). Your listeners will become part of your new component providing components behavior.

From the design and program organization point of view this is much more superior approach.

eugener
A: 

Here is some old code which shows how to create a "round" JButton. I would extend JComponent instead and the important methods to override are paintComponent() and contains():

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 );

    }
}

This simplifies the hit detection easily since there is no custom code. Also it allows you to control overlapping of compnents easily since you can control the Z-Order of each component.

camickr
Thanks this is very useful!
TotalCruise