代码之家  ›  专栏  ›  技术社区  ›  Allain Lalonde

使组件对Swing中的拖动不那么敏感

  •  6
  • Allain Lalonde  · 技术社区  · 16 年前

    A. JComponent 我的人正在开枪 mouseDragged 事件过于激烈。当用户试图点击时,即使鼠标只移动了1个像素,它也会被解释为拖动。

    我如何为一个特定的组件添加一个规则,该规则相当于:

    除非满足以下条件,否则不要将其视为拖动事件 鼠标已经移动了10个像素 被按下的点。

    注意:我知道这不是我操作系统中的系统设置,因为只有该组件上的事件才会受到这种过度敏感的影响。

    非常感谢。

    4 回复  |  直到 16 年前
        1
  •  6
  •   farincz    11 年前

    将之前的答案结合在一起,并使用适当的事件类型:

    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);
        }
    }
    
        2
  •  4
  •   L. Cornelius Dol    16 年前

    我以前就必须这样做。这是我的鼠标事件处理代码,精简到与拖动相关的部分,在被视为拖动之前需要几个像素。

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

    请注意,我也遇到了一些问题 Java 一些JVM在拖动后生成点击事件,我必须检测并抑制这些事件。

        3
  •  1
  •   JMD    16 年前

    如果我没记错的话,你正在跟踪点击和鼠标拖动事件。你能在鼠标放下时跟踪坐标,然后在鼠标拖动中进行短暂的计算,看看鼠标是否移动了你想要的最小像素数吗?当然,您还希望在mouseup或鼠标拖动到JComponent边界之外时取消/重置。

    警告:我自己还没有做过,但我认为如果是我,我会从这里开始。

        4
  •  0
  •   Alexander Malfait    14 年前

    Software Monkey的代码似乎缺少一些代码,所以我写了这个解决方案:

    navigationTree.addMouseListener(new DragInsensitiveMouseClickListener(10) {
        @Override
        public void mouseClicked(MouseEvent e) {
            TreePath treePath = navigationTree.getPathForLocation(e.getX(), e.getY());
    
            if(treePath != null) {
                processChoice();
            }
        }
    });
    

    当用户产生最多10像素的“拖动行程”时,这仍将触发mouseClicked()事件。

    点击监听器的代码:

    import java.awt.Point;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    
    public class DragInsensitiveMouseClickListener extends MouseAdapter {
    
        private final int allowedTravel;
    
        public Point mouseDownPoint;
    
        public DragInsensitiveMouseClickListener(int allowedTravel) {
            this.allowedTravel = allowedTravel;
        }
    
        @Override
        public void mousePressed(MouseEvent e) {
            mouseDownPoint = e.getPoint();
        }
    
        @Override
        public void mouseReleased(MouseEvent e) {
            double horizontalTravel = Math.abs(mouseDownPoint.getX() - e.getX());
            double verticalTravel = Math.abs(mouseDownPoint.getY() - e.getY());
    
            if (horizontalTravel < allowedTravel && verticalTravel < allowedTravel) {
                mouseClicked(e);
            }
        }
    }