有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java什么是最好的UI元素拖动算法

我制作了一个GUI应用程序,但我一直使用一个变通算法,将ui元素相对于另一个表面(屏幕、画布等)进行拖动/移动。在我的例子中,我使用它作为相对于屏幕的窗口,但这不是重点,因为这个算法应该在任何可能的地方都能工作。这是我的算法:

代码清单1

MouseMotionAdapter(){
            int prevX = -1000, prevY = -1000, getX, getY;
            public void mouseDragged(MouseEvent e) {
              //if initial cursor position isn't set 
                if(prevX==-1000){
                    prevX = e.getLocationOnScreen().x;
                    prevY = e.getLocationOnScreen().y;
                    getX = e.getX();
                    getY = e.getY();
                }
               //move element to new position 
                theFrame.setBounds(theFrame.getBounds().x+e.getX()-getX, theFrame.getBounds().y+e.getY()-getY, 880, 583);
                prevX=e.getLocationOnScreen().x;
                prevY=e.getLocationOnScreen().y;
            }

该算法的问题在于,鼠标光标的位置相对于元素是固定的,如果我试图移动/拖动元素,点击元素的另一个位置/部分,整个元素都会移动,从而鼠标光标定位在“初始位置”,这不是我想要的行为(我希望它具有我们通常知道的行为,比如当我们移动桌面上的图标或屏幕上的窗口时,等等)

有人能帮忙吗?提前谢谢


共 (1) 个答案

  1. # 1 楼答案

    在这种情况下,通常的方法是计算当前位置和先前位置之间的差值。该差异即“移动”,即添加到拖动对象的位置

    (顺便说一句:您似乎根本没有在计算中使用prev...值!)

    MouseMotionListener中,大致如下所示:

    class MouseDraggingControl implements MouseMotionListener 
    {
        private Point previousPoint = new Point();
    
        @Override 
        public void mouseMoved(MouseEvent e)
        {
            previousPoint = e.getPoint();
        }
    
        @Override 
        public void mouseDragged(MouseEvent e)
        {
            int movementX = e.getX() - previousPoint.x;
            int movementY = e.getY() - previousPoint.y;
    
            doMovement(movementX, movementY);
    
            previousPoint = e.getPoint();
        }
    }
    

    在您的情况下,doMovement方法的实现方式如下:

    private void doMovement(int movementX, int movementY)
    {
        int oldX = theFrame.getX();
        int oldY = theFrame.getY();
        int newX = oldX + movementX;
        int newY = oldY + movementY;
        theFrame.setLocation(newX, newY);
    }
    

    (或类似,使用getBounds/setBounds调用)


    编辑如果鼠标运动监听器直接连接到应拖动的组件,则可能需要使用“屏幕上的位置”:

    class MouseDraggingControl implements MouseMotionListener 
    {
        private Point previousPoint = new Point();
    
        @Override 
        public void mouseMoved(MouseEvent e)
        {
            previousPoint = e.getLocationOnScreen();
        }
    
        @Override 
        public void mouseDragged(MouseEvent e)
        {
            Point p = e.getLocationOnScreen();
            int movementX = p.x - previousPoint.x;
            int movementY = p.y - previousPoint.y;
    
            doMovement(movementX, movementY);
    
            previousPoint = e.getLocationOnScreen();
        }
    }
    

    如果这不能解决您的问题,我想强调MadProgrammer的评论:一个演示实际问题的示例在这里会有所帮助