Java中的mouseEvent方法让人疯狂

Java中的mouseEvent方法让人疯狂,java,Java,一个星期过去了,我正忙着解决这个问题。它应该是一个简单的练习: 我有一个长方形。我单击并拖动x轴上的矩形。矩形应仅在设置的边界区域(画布)内移动,因此如果画布宽度为200 px,则x坐标应仅从0移动到getWidth()-rectangle\u WIDTH 很简单,但我就是做不到 下面是我笨拙的代码 我附加了两个glabel来查看坐标。我注意到mouseMoved标签将只显示画布内的坐标(我想要的),但是mouseDragged标签将变为负数,并且还将显示画布外的坐标这也是矩形对象移动被控制的地

一个星期过去了,我正忙着解决这个问题。它应该是一个简单的练习:

我有一个长方形。我单击并拖动x轴上的矩形。矩形应仅在设置的边界区域(画布)内移动,因此如果画布宽度为200 px,则x坐标应仅从0移动到
getWidth()-rectangle\u WIDTH

很简单,但我就是做不到

下面是我笨拙的代码

我附加了两个glabel来查看坐标。我注意到mouseMoved标签将只显示画布内的坐标(我想要的),但是mouseDragged标签将变为负数,并且还将显示画布外的坐标这也是矩形对象移动被控制的地方。我不知道为什么这两种行为是不同的

现在,我的发言如下:

if ((gobj.getX()) > 0 && (gobj.getX()) < (APPLICATION_WIDTH - PADDLE_WIDTH)){
     gobj.move(e.getX() - lastX, 0);                
} 
if((gobj.getX())>0&&(gobj.getX())<(应用程序宽度-挡板宽度)){
move(e.getX()-lastX,0);
} 
到目前为止,该语句所做的是将矩形移到边缘,但它只是停留在那里,不会返回。我在这件事上大发脾气

import java.awt.*;
import java.awt.event.*;
import acm.graphics.*;
import acm.program.*;

/** This class displays a mouse-draggable rectangle and oval */

public class DragObject extends GraphicsProgram {

private static final int PADDLE_WIDTH = 150;
public static final int APPLICATION_WIDTH = 700;

    public void run() {

        GRect rect = new GRect(100, 100, 150, 100);
        rect.setFilled(true);
        rect.setColor(Color.RED);   
        add(rect);

        label2 = new GLabel ("");
        add(label2, 300, 400);


        label = new GLabel ("");
        add(label, 300, 300);
        addMouseListeners();


    }

    /* these coordinates are never going beyond the canvas-even if the 
     * mouse does...this is good...i want this   */

    public void mouseMoved(MouseEvent e){

        label2.setLabel("Coordinates:" + e.getX() + ", " + e.getY());

    }

/** Called on mouse press to record the coordinates of the click */
    public void mousePressed(MouseEvent e) {
        lastX = e.getX();
        lastY = e.getY();
        gobj = getElementAt(lastX, lastY);

    }

/** Called on mouse drag to reposition the object */
    public void mouseDragged(MouseEvent e) { 

          if ((gobj.getX()) > 0 && (gobj.getX()) < (APPLICATION_WIDTH - PADDLE_WIDTH)){
            gobj.move(e.getX() - lastX, 0);

           } 

            lastX = e.getX();


            /* This label is active when i click the object, and does go into negative 
             * numbers and still counts even when off the canvas...*/
            label.setLabel("Coordinates:" + e.getX() + ", " + e.getY());
    }

/* Instance variables */

private GLabel label2;
private GLabel label;
private GObject gobj;   /* The object being dragged */
private double lastX;   /* The last mouse X position */
private double lastY;   /* The last mouse Y position */
}
import java.awt.*;
导入java.awt.event.*;
导入acm图形。*;
导入acm.程序。*;
/**此类显示鼠标拖动的矩形和椭圆形*/
公共类DragObject扩展图形程序{
专用静态最终内桨_宽度=150;
公共静态最终整数应用程序\u宽度=700;
公开募捐{
GRect rect=新的GRect(100100150100);
rect.setFilled(true);
矩形设置颜色(颜色为红色);
添加(rect);
label2=新的GLabel(“”);
添加(标签2300400);
标签=新GLabel(“”);
添加(标签,300300);
addMouseListeners();
}
/*这些坐标永远不会超出画布,即使
*老鼠做…这很好…我想要这个*/
public void mouseMoved(MouseEvent e){
标签2.setLabel(“坐标:“+e.getX()+”,“+e.getY());
}
/**调用鼠标按键来记录单击的坐标*/
公共无效鼠标按下(MouseEvent e){
lastX=e.getX();
lastY=e.getY();
gobj=getElementAt(lastX,lastY);
}
/**在鼠标拖动时调用以重新定位对象*/
公共无效mouseDragged(MouseEvent e){
如果((gobj.getX())>0&&(gobj.getX())<(应用程序宽度-挡板宽度)){
move(e.getX()-lastX,0);
} 
lastX=e.getX();
/*当我单击该对象时,该标签处于活动状态,并进入负片状态
*数字和仍然计数,即使离开画布*/
setLabel(“坐标:“+e.getX()+”,“+e.getY());
}
/*实例变量*/
私人GLabel label2;
私人GLabel标签;
private GObject gobj;/*正在拖动的对象*/
private double lastX;/*最后一个鼠标X位置*/
private double lastY;/*最后一个鼠标Y位置*/
}

您可以通过设计将组件拖出,甚至拖出窗口,以支持拖放

对于拖动事件,只需将事件位置约束到其容器内:

static public final int MAX_X=(CANVAS_WIDTH - PADDLE_WIDTH);

...

public void mouseDragged(MouseEvent e) { 
    int px=Math.max(0,Math.min(e.getX(),MAX_X));
    int dx=(px-lastX);

    if(dx!=0) { 
        gobj.move(dx); 
        lastX=px;
        }
    }

在熟睡之后,重新阅读了注释,我知道问题可能出在哪里了——没有显示GObject提供的代码,也没有显示它是如何创建/初始化的。所以很难猜测问题中代码的上下文

我敢打赌,桨叶最初是在帆布的中间(也许是中间/底部)创造的。上面的代码,以及问题中的代码,仅约束一个增量,以防止增量超出画布的边界-它不考虑桨的初始位置。也就是说,如果挡板从x=350开始,并且增量允许总计700-150=550,则受约束的增量将允许挡板移动到350-550=-200,挡板将移动到左边缘以外的200像素


因此,您需要将上限传递给move方法,并将结果位置约束为0 ok。这对于拖放是有意义的,但是如何约束事件位置呢?这就是让我发疯的原因。嗯,这并没有达到预期的效果。向左移动鼠标会向右移动矩形,反之亦然。另外,尽管它在边界框处停止,但如果我再次单击并拖动,矩形将从屏幕上移开…更改这一行:int dx=(px-lastX);修复了反转,但我仍然没有始终只击中边界框的边缘…如果我移动鼠标,有时松开按钮,我就会从框中出来,等等@Joel:还转储dx和px,看看它们是否做了任何意外的事情。@Joel:为什么不约束它的setter/move?将getter更改为“lie”似乎是错误的,因为setter应该防止从无效值开始。
    ...
    if(dx!=0) { 
        gobj.moveX(dx,MAX_X); 
        lastX=px;
        }
    ...
public void moveX(int dlt, int max) {
    positionX=Util.limitInt((positionX+dlt),0,max);
    }
/**
 * Limit the range of a number to the specified values.
 */
static public int limitInt(int val, int low, int hgh) {
    return ((val<low) ? low : ((val<hgh) ? val : hgh));
    }
public void move(int dltX, int maxX, int dltY, int maxY) {
    positionX=Util.limitInt((positionX+dltX),0,maxX);
    positionY=Util.limitInt((positionX+dltY),0,maxY);
    }