简体   繁体   English

鼠标移动侦听器仅在一个方向上

[英]mouse motion listener only in one direction

i have been working on mouse motion listener in Java couldn't sort it out completely because i want the object to move towards the direction where ever on the screen the mouse is pointed at but unforunately when the mouse is inside the applet window, the object moves only towards a single direction. 我一直在用Java开发鼠标运动侦听器,无法完全解决问题,因为我希望对象朝着鼠标所指向的屏幕方向移动,但是不幸的是,当鼠标位于applet窗口中时,该对象仅向单个方向移动。 Here is my code below.. 这是我的下面代码。

import java.awt.*;
import java.awt.geom.*;
import java.util.*;
import java.applet.*;
import java.awt.event.*;
import javax.swing.*;

public class MouseOver extends Applet implements KeyListener, MouseListener,
      MouseMotionListener {
   private int[] Xpoints = { 0, -5, 5 };
   private int[] Ypoints = { -10, -2, -2 };
   private double xpos, ypos;
   private Polygon poly;
   int polyrot = 0;
   private int width; // !! added
   private int height; // !! added

   public void init() {
      poly = new Polygon(Xpoints, Ypoints, Xpoints.length);
      addKeyListener(this);
      addMouseListener(this);
      addMouseMotionListener(this);
   }

   public void paint(Graphics g) {
      Graphics2D g2d = (Graphics2D) g;
      AffineTransform id = new AffineTransform();
      width = getSize().width;
      height = getSize().height;
      g2d.setColor(Color.BLACK);
      g2d.fillRect(0, 0, width, height);
      g2d.setColor(Color.RED);
      g2d.draw(poly);
      g2d.translate(width / 2, height / 2);
      g2d.rotate(Math.toRadians(polyrot));
      g2d.scale(5, 5);
   }

   public void keyReleased(KeyEvent k) {
   }

   public void keyTyped(KeyEvent k) {
   }

   public void keyPressed(KeyEvent k) {
      switch (k.getKeyCode()) {
      case KeyEvent.VK_LEFT:
         if (polyrot < 0) {
            polyrot = 359;
            polyrot++;
         }
         repaint();
         break;
      case KeyEvent.VK_RIGHT:
         if (polyrot > 360) {
            polyrot = 0;
            polyrot--;
         }
         repaint();
         break;
      }
   }

   public void mouseEntered(MouseEvent m) {
   }

   public void mouseExited(MouseEvent m) {
   }

   public void mouseReleased(MouseEvent m) {
   }

   public void mouseClicked(MouseEvent m) {
   }

   public void mousePressed(MouseEvent m) {
      switch (m.getButton()) {
      case MouseEvent.BUTTON1:
         if (polyrot < 0) {
            polyrot = 359;
            polyrot--;
         }
         repaint();
         break;
      case MouseEvent.BUTTON2:
         if (polyrot > 360) {
            polyrot = 0;
            polyrot++;
         }
         repaint();
         break;
      }
   }

   public void mouseMoved(MouseEvent e) {
      xpos = getX();
      if (xpos < 0) {
         polyrot--;
      } else if (xpos > 0) {
         polyrot++;
      }
      repaint();
      // !! break; // Doesn't belong here
   }

   @Override
   public void mouseDragged(MouseEvent e) {
      // You forgot this method
   }
}

Your problem is with this line: 您的问题是与此行:

public void mouseMoved(MouseEvent e){
 xpos=getX(); // ******
 if(xpos<0){polyrot--;}
 else if(xpos>0){polyrot++;}
 repaint();
 break;
}

That returns the x position of the applet not the mouse cursor. 这将返回小程序的x位置而不是鼠标光标。 You need to use your MouseEvent object, e and instead get the mouse's position. 您需要使用MouseEvent对象e来获取鼠标的位置。 Change it to: 更改为:

xpos = e.getX();

Please don't ignore the comment that I made to your question. 请不要忽略我对您的问题的评论。 Please remember that we're volunteers who help on our free time. 请记住,我们是自愿者,他们为我们的业余时间提供帮助。 Please don't make it any more difficult than it has to be to help you. 请不要比帮助您困难得多。


I've tried to edit your code so that it compiles, and now is indented. 我试图编辑您的代码,使其能够编译,现在缩进了。 Consider creating a Swing application, not an AWT application, since Swing apps are more flexible, powerful and robust. 考虑创建Swing应用程序,而不是AWT应用程序,因为Swing应用程序更灵活,功能更强大且更强大。

There are a few things... 有几件事...

In your keyPressed and mousePressed events, are are only ever process the out of bounds conditions, for example... keyPressedmousePressed事件中,仅处理越界条件,例如...

if (polyrot < 0) {
    polyrot = 359;
    polyrot++;
}
//...
if (polyrot > 360) {
    polyrot = 0;
    polyrot--;
}

But you never process what it should do when it's within the acceptable bounds (0-359)... 但是当它在可接受的范围内(0-359)时,您永远不会处理它应该做什么。

Instead, you could simply add or subtract the amount from polyrot and allow the API to deal with it (surprisingly, it's capable for dealing with angles < 0 and > 359), for example... 相反,您可以简单地从polyrot添加或减去数量,并允许API处理它(令人惊讶的是,它能够处理<0和> 359的角度),例如...

public void mousePressed(MouseEvent m) {
    switch (m.getButton()) {
        case MouseEvent.BUTTON1:
            polyrot--;
            repaint();
            break;
        case MouseEvent.BUTTON2:
            polyrot++;
            repaint();
            break;
    }
}

Now, I'm not sure what you mean by "object to move towards the direction where ever on the screen the mouse is pointed" . 现在,我不确定“对象朝着鼠标指向屏幕的方向移动”的含义。 Does this mean that the object should actually change it's x/y coordinates or should it just "look" at the mouse cursor... 这是否意味着该对象实际上应该更改其x / y坐标,还是只是“看”鼠标光标...

Based on the fact that you actually have no movement code and you basically have the object painted in a fixed location, I'm assuming "look at"... 基于您实际上没有移动代码并且基本上将对象绘制在固定位置这一事实,我假设“看一下” ...

Basically, you need to know where the mouse is and where the object is, then determine the angle between them... 基本上,您需要知道鼠标在哪里以及对象在哪里,然后确定它们之间的角度...

public void mouseMoved(MouseEvent e) {
    int x = width / 2;
    int y = height / 2;

    Point mousePoint = e.getPoint();

    int deltaX = mousePoint.x - x;
    int deltaY = mousePoint.y - y;

    polyrot = -Math.atan2(deltaX, deltaY);
    polyrot = Math.toDegrees(polyrot) + 180;

    repaint();
}

You should note that I changed 'polyrot' to 'double' 您应该注意,我将“ polyrot”更改为“ double”

Your paint method is also wrong. 您的paint方法也是错误的。 Basically, you are painting your object BEFORE you've transformed it, instead, you should be using something more like... 基本上,您是在变换对象之前绘制对象,相反,您应该使用更类似的东西...

g2d.translate(width / 2, height / 2);
g2d.rotate(Math.toRadians(polyrot));
g2d.draw(poly);

You should also be calling super.paint(g) before you apply you own custom painting... 在应用自己的自定义绘画之前,还应该调用super.paint(g)

As a side note, you should avoid overriding paint of top level containers, like JApplet , but instead, create a custom component, extending from something like JPanel and override it's paintComponent method, performing your custom painting there (don't forget to call super.paintComponent ). 附带说明一下,您应该避免覆盖顶级容器(如JApplet paint ,而应创建一个自定义组件,从JPanel类扩展并覆盖其paintComponent方法,在此处执行自定义绘制(不要忘记调用super.paintComponent )。 Take a look at Performing Custom Painting for more details 请看表演自定义绘画以了解更多详细信息

You should also avoid using KeyListener and instead use the Key Bindings API as it doesn't suffer from the same focus issues that KeyListener does... 您还应该避免使用KeyListener ,而应使用Key Bindings API,因为它不会像KeyListener那样受到相同的焦点问题的困扰...

Updated with runnable example 更新了可运行示例

So I had a play around with code and produced this simple example... 所以我玩弄了代码并制作了这个简单的示例...

在此处输入图片说明

Basically, I tossed out Polygon in favour of Path2D , basically because it provides much greater functionality and is easy to deal with when scaling ;) 基本上,我抛弃了Polygon ,转而使用Path2D ,基本上是因为它提供了更多功能,并且在缩放时易于处理;)

import java.applet.Applet;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;

public class MouseOver extends Applet implements KeyListener, MouseListener,
                MouseMotionListener {

    private double xpos, ypos;
    private Path2D poly;
    private double polyrot = 0;
    private int width; // !! added
    private int height; // !! added

    public void init() {
        poly = new Path2D.Double();
        poly.moveTo(0, 10);
        poly.lineTo(5, 0);
        poly.lineTo(10, 10);
        poly.lineTo(0, 10);
        poly.closePath();
        addKeyListener(this);
        addMouseListener(this);
        addMouseMotionListener(this);
    }

    public void paint(Graphics g) {
        super.paint(g);;

        Graphics2D g2d = (Graphics2D) g;
        AffineTransform id = new AffineTransform();
        width = getSize().width;
        height = getSize().height;
        g2d.setColor(Color.BLACK);
        g2d.fillRect(0, 0, width, height);
        g2d.setColor(Color.RED);

        id.scale(5, 5);
        Shape scaled = poly.createTransformedShape(id);

        Rectangle bounds = scaled.getBounds();        
        g2d.translate((width - bounds.width) / 2, (height - bounds.height) / 2);
        g2d.rotate(Math.toRadians(polyrot), bounds.width / 2, bounds.height / 2);

        g2d.setStroke(new BasicStroke(5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));

        g2d.draw(scaled);
    }

    public void keyReleased(KeyEvent k) {
    }

    public void keyTyped(KeyEvent k) {
    }

    public void keyPressed(KeyEvent k) {
        switch (k.getKeyCode()) {
            case KeyEvent.VK_LEFT:
                polyrot++;
                repaint();
                break;
            case KeyEvent.VK_RIGHT:
                polyrot--;
                repaint();
                break;
        }
    }

    public void mouseEntered(MouseEvent m) {
    }

    public void mouseExited(MouseEvent m) {
    }

    public void mouseReleased(MouseEvent m) {
    }

    public void mouseClicked(MouseEvent m) {
    }

    public void mousePressed(MouseEvent m) {
        switch (m.getButton()) {
            case MouseEvent.BUTTON1:
                polyrot--;
                repaint();
                break;
            case MouseEvent.BUTTON2:
                polyrot++;
                repaint();
                break;
        }
    }

    public void mouseMoved(MouseEvent e) {
        int x = width / 2;
        int y = height / 2;

        Point mousePoint = e.getPoint();

        int deltaX = mousePoint.x - x;
        int deltaY = mousePoint.y - y;

        polyrot = -Math.atan2(deltaX, deltaY);
        polyrot = Math.toDegrees(polyrot) + 180;

        repaint();
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        // You forgot this method
    }
}

This: 这个:

  if (xpos < 0) {

means "if the cursor is outside of the panel". 表示“如果光标在面板之外”。

This: 这个:

  xpos = getX();

does not get a mouse coordinate. 没有鼠标坐标。

Change your event to something like this: 将您的活动更改为以下内容:

public void mouseMoved(MouseEvent e) {
    xpos = e.getX();
    if (xpos < getWidth() / 2) {
        polyrot--;
    } else {
        polyrot++;
    }
    repaint();
}

Now it rotates counter-clockwise if the cursor is on the left side of the panel and clockwise if the cursor is on the right side. 现在,如果光标在面板的左侧,它将逆时针旋转;如果光标在右侧,则将逆时针旋转。

This: 这个:

  g2d.draw(poly);
  g2d.translate(width / 2, height / 2);
  g2d.rotate(Math.toRadians(polyrot));
  g2d.scale(5, 5);

will not do anything to change the image because you are doing your transforming after drawing it. 不会做任何更改图像的操作,因为您在绘制图像后进行了转换。

This: 这个:

  Graphics2D g2d = (Graphics2D) g;

is a bad idea because you are applying transforms to the global graphics context which would carry on to subsequent repaints of other components. 这是一个坏主意,因为您要将变换应​​用于全局图形上下文,这将继续进行其他组件的后续重绘。

Change your paint to something like this: 将油漆更改为以下内容:

public void paint(Graphics g) {
    super.paint(g);
    Graphics2D g2d = (Graphics2D) g.create();
    width = getSize().width;
    height = getSize().height;
    g2d.setColor(Color.BLACK);
    g2d.fillRect(0, 0, width, height);
    g2d.translate(width / 2, height / 2);
    g2d.rotate(Math.toRadians(polyrot));
    g2d.scale(5, 5);
    g2d.setColor(Color.RED);
    g2d.draw(poly);
    g2d.dispose();
}

Further reading: 进一步阅读:

From here: 从这里:

public void mouseMoved(MouseEvent e){
 xpos=getX();
 if(xpos<0){polyrot--;}
 else if(xpos>0){polyrot++;}
 repaint();
 break;
}

It seems you update only the xpos. 看来您只更新了xpos。 You should update also the variable ypos. 您还应该更新变量ypos。 You might want to do it with something like this: 您可能想使用以下方法进行操作:

ypos=e.getY();
if (this.ypos<0){
 this.polyrot--;
}else if (this.ypos>0) {
 this.polyrot++;
}
this.repaint();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM