views:

772

answers:

3

The effect I've been trying to create is that the mouse cursor icon changes whenever the mouse enters a certain zone on a JPanel, and switches to default whenever it leaves the zone. I'm using the MouseMoved feature in the MouseMotionListener class, which whenever the mouse moves over the JPanel verifies if the coordinates correspond to the special area.

However, the strain on the computer's processor is very high with this method, so I wanted to ask if there's a more efficient way of doing it. Any help is appreciated.

What the program does is it draws figures on a JPanel, and when the Connection button is selected then it connects those figures with a line if the user clicks on one figure, and then on another.

The figures are drawn on the JPanel, and have their respective region boundaries stored, so when the mouse moves it checks if the current X and Y coordinates are inside one of those regions, and if so changes cursor. The checkValidConnectionRegion checks to see if the current X and Y variables are inside a figure's region. Here's the code for the handler:

public void mouseMoved(MouseEvent e)
    {
        if(GUI.Connectionbutton.isSelected())
        {
            x = e.getX();
            y = e.getY();

            checkValidConnectionRegion(); 

            if(validConnectionRegion)
                setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
            if(!validConnectionRegion)
                setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
        }
    }
+2  A: 

You're probably running inefficient code in your MouseMoved handler.

Can you post the entire source for your MouseMoved handler?

SLaks
Alright I'll edit the question and post the code.
Hans
+5  A: 

A more efficient approach would be to add a child JPanel to the parent JPanel, which would act as the invisible area. Then simply set the cursor on the child JPanel and the mouse pointer should change when you move over it.

JPanel mainPnl = new JPanel(new BorderLayout());

JPanel invisibleArea = new JPanel();
invisibleArea.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
invisibleArea.setPreferredSize(new Dimension(100, 100));

mainPnl.add(invisibleArea, BorderLayout.WEST);
Adamski
I'm thinking this would be a way to do it, but I would need to change the whole way figures are drawn.
Hans
Hmm, or I could still draw the figures on the main panel, and when the "Connection Button" is selected set each invisible area visible.
Hans
+1  A: 

I'm not familiar with Java, but the problem might be that Cursor.getPredefinedCursor is creating a new cursor instance everytime you call it. (I don't know if that is true)

Try making two final fields in your class for the two cursors and setting them only once.

Also, try only stetting the cursor if validConnectionRegion actually changed.

For example:

final Cursor crosshairCursor = Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
final Cursor defaultCursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);

public void mouseMoved(MouseEvent e)
{
    if(GUI.Connectionbutton.isSelected())
    {
        x = e.getX();
        y = e.getY();

        boolean wasValid = validConnectionRegion;
        checkValidConnectionRegion(); 

        if(wasValid != validConnectionRegion)
            setCursor(validConnectionRegion ? crosshairCursor : defaultCursor);
    }
}
SLaks