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