Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a component less sensitive to Dragging in Swing

A JComponent of mine is firing a mouseDragged event too vigorously. When the user is trying to click, it interprets is as a drag even if the mouse has only moved 1 pixel.

How would I add a rule for a particular component that amounted to:

Do not consider it a drag event unless the mouse has moved 10 pixels from the point at which is was pressed down.

Note: I know it's not a system setting in my OS, since only events on that component suffer from this over sensitivity.

Thank you.

like image 843
Allain Lalonde Avatar asked Feb 06 '09 21:02

Allain Lalonde


3 Answers

Previous answers combined together, with proper event type:

public class DragInsensitiveMouseClickListener implements MouseInputListener {

    protected static final int MAX_CLICK_DISTANCE = 15;

    private final MouseInputListener target;

    public MouseEvent pressed;

    public DragInsensitiveMouseClickListener(MouseInputListener target) {
        this.target = target;
    }

    @Override
    public final void mousePressed(MouseEvent e) {
        pressed = e;
        target.mousePressed(e);
    }

    private int getDragDistance(MouseEvent e) {
        int distance = 0;
        distance += Math.abs(pressed.getXOnScreen() - e.getXOnScreen());
        distance += Math.abs(pressed.getYOnScreen() - e.getYOnScreen());
        return distance;
    }

    @Override
    public final void mouseReleased(MouseEvent e) {
        target.mouseReleased(e);

        if (pressed != null) {
            if (getDragDistance(e) < MAX_CLICK_DISTANCE) {
                MouseEvent clickEvent = new MouseEvent((Component) pressed.getSource(),
                        MouseEvent.MOUSE_CLICKED, e.getWhen(), pressed.getModifiers(),
                        pressed.getX(), pressed.getY(), pressed.getXOnScreen(), pressed.getYOnScreen(),
                        pressed.getClickCount(), pressed.isPopupTrigger(), pressed.getButton());
                target.mouseClicked(clickEvent);
            }
            pressed = null;
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        //do nothing, handled by pressed/released handlers
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        target.mouseEntered(e);
    }

    @Override
    public void mouseExited(MouseEvent e) {
        target.mouseExited(e);
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        if (pressed != null) {
            if (getDragDistance(e) < MAX_CLICK_DISTANCE) return; //do not trigger drag yet (distance is in "click" perimeter
            pressed = null;
        }
        target.mouseDragged(e);
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        target.mouseMoved(e);
    }
}
like image 163
farincz Avatar answered Sep 21 '22 01:09

farincz


I've had to do exactly this before. Here's my mouse event processing code, cut down to just the bits relating to making drag require a few pixels before being treated as a drag.

public void mousePressed(int mod, Point loc) {
    pressLocation=copyLocation(loc,pressLocation);
    dragLocation=null;
    }

public void mouseReleased(int mod, Point loc) {
    if(pressLocation!=null && dragLocation!=null) {
        // Mouse drag reverted to mouse click - not dragged far enough
        // action for click
        pressLocation=null;
        }
    else if(dragLocation!=null) {
        // action for drag completed
        }
    else {
        // do nothing
        }

    pressLocation=null;
    dragLocation=null;
    }

public void mouseDragged(int mod, Point loc) {
    if(pressLocation!=null) {                                                   // initial drag actions following mouse press
        dragLocation=pressLocation;                                             // consider dragging to be from start point
        if(Math.abs(loc.x-pressLocation.x)<dragMinimum && Math.abs(loc.y-pressLocation.y)<dragMinimum) {
            return;                                                             // not dragged far enough to count as drag (yet)
            }
        // action drag from press location
        pressLocation=null;
        }
    else {
        // action drag from last drag location
        dragLocation=copyLocation(loc,dragLocation);
        }
    }

And note, I also had problems with Java some JVM's generating click events after dragging, which I had to detect and suppress.

like image 34
Lawrence Dol Avatar answered Sep 21 '22 01:09

Lawrence Dol


If I read your question correctly, you're tracking both click and mousedrag events. Can you track the coordinates upon mousedown, followed by a short computation in mousedrag to see if the mouse has moved your desired minimum numbers of pixels? Of course, you then also want to cancel/reset on mouseup or when the mouse is dragged outside the bounds of your JComponent.

Caveat: I haven't done this myself, but I think it's where I'd start if it were me.

like image 28
JMD Avatar answered Sep 22 '22 01:09

JMD