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

Java 什么是最好的UI元素拖动算法,java,algorithm,Java,Algorithm,我制作了一个GUI应用程序,但我一直使用一个变通算法,将ui元素相对于另一个表面(屏幕、画布等)进行拖动/移动。在我的例子中,我使用它作为相对于屏幕的窗口,但这不是重点,因为这个算法应该在任何可能的地方都能工作。这是我的算法: code-listing-1. MouseMotionAdapter(){ int prevX = -1000, prevY = -1000, getX, getY; public void mouseDragged(Mou

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

code-listing-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;
            }
该算法的问题在于,鼠标光标的位置相对于元素是固定的,如果我尝试移动/拖动元素,单击元素的另一个位置/部分,整个元素都会移动,从而将鼠标光标定位在“初始位置”,这不是我想要的行为(我希望它具有我们最熟悉的行为,比如在桌面上移动图标或在屏幕上移动窗口等)


有人能帮忙吗?提前谢谢。

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

(顺便说一句:您似乎根本没有在计算中使用
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
调用)


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


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

您应该在
mouseDown
方法中设置初始位置。一些提示-(1)“问题”这一段有点难理解——在解释中加入一些实际坐标和屏幕截图可能会有所帮助。(但用户3386109在这个问题上可能是正确的)(2)在提出问题之前,您应该始终尝试调试代码。虽然调试有关鼠标事件的代码是公认的困难,但插入一些打印语句来显示变量何时执行以及如何更改并不是那么困难。实际操作将涉及更少的猜测工作和更好的响应。当我使用是algorithm@PaikuHan添加了一个编辑-如果这没有帮助,您可能需要更详细地描述您当前的设置。只是为了确保(因为它可以工作)。所有抖动错误背后的原因是,我实际上设置了被拖动元素相对于鼠标位置的边界,而鼠标位置不是我试图拖动元素的表面(即,当元素位于B而不是a时,将鼠标位置移到表面a上,以将被拖动元素移到与a不同的表面B上)我是对的?我不明白你问题的细节(A,B,什么?)-但简单地说:当一个“鼠标标记”事件发生,然后移动发生此事件的组件,后续事件将根据组件的新位置引用鼠标坐标。这会导致在计算与旧位置的差异时结果不一致,因为旧位置仍然引用被拖动组件的旧位置。如果这不能回答问题,我可以尝试添加一个草图。@PaikuHan不可否认,我很难确定问题最初是由什么引起的(我没有一个可运行的示例来测试这个问题)。但是“抖动”表明您获取了错误的坐标,可能是从移动之前和之后的组件获取的。
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();
    }
}