Слушатель движения мыши только в одном направлении
Я работал над обработчиком движений мыши в Java, но не смог разобраться в этом полностью, потому что я хочу, чтобы объект двигался в направлении, куда когда-либо на экране была указана мышь, но, к сожалению, когда мышь находится внутри окна апплета, объект движется только в одном направлении. Вот мой код ниже..
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
}
}
4 ответа
Ваша проблема с этой строкой:
public void mouseMoved(MouseEvent e){
xpos=getX(); // ******
if(xpos<0){polyrot--;}
else if(xpos>0){polyrot++;}
repaint();
break;
}
Это возвращает позицию апплета x, а не курсор мыши. Вам нужно использовать объект MouseEvent, e и вместо этого получить позицию мыши. Измените это на:
xpos = e.getX();
Пожалуйста, не игнорируйте мой комментарий к вашему вопросу. Пожалуйста, помните, что мы добровольцы, которые помогают в наше свободное время. Пожалуйста, не усложняйте, чем помогать вам.
Я пытался отредактировать ваш код так, чтобы он компилировался, и теперь с отступом. Подумайте о создании приложения Swing, а не приложения AWT, поскольку приложения Swing более гибкие, мощные и надежные.
Есть несколько вещей...
В вашем keyPressed
а также mousePressed
события, которые только когда-либо обрабатывают вне пределов условий, например...
if (polyrot < 0) {
polyrot = 359;
polyrot++;
}
//...
if (polyrot > 360) {
polyrot = 0;
polyrot--;
}
Но вы никогда не обрабатываете то, что должно делать, когда оно находится в допустимых пределах (0-359)...
Вместо этого вы можете просто добавить или вычесть сумму из polyrot
и позволить API справиться с этим (к удивлению, он способен работать с углами < 0 и> 359), например...
public void mousePressed(MouseEvent m) {
switch (m.getButton()) {
case MouseEvent.BUTTON1:
polyrot--;
repaint();
break;
case MouseEvent.BUTTON2:
polyrot++;
repaint();
break;
}
}
Теперь, я не уверен, что вы подразумеваете под "объектом для перемещения в направлении, где когда-либо на экране указана мышь". Означает ли это, что объект должен фактически изменить свои координаты x/y или он должен просто "смотреть" на курсор мыши...
Исходя из того факта, что у вас фактически нет кода движения, и вы в основном закрашиваете объект в фиксированном месте, я предполагаю "посмотреть"...
По сути, вам нужно знать, где находится мышь и где находится объект, а затем определить угол между ними...
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();
}
Вы должны заметить, что я изменил 'polyrot' на 'double'
Ваш paint
Метод тоже неверен. По сути, вы рисуете свой объект, прежде чем вы изменили его, вместо этого вы должны использовать что-то более похожее на...
g2d.translate(width / 2, height / 2);
g2d.rotate(Math.toRadians(polyrot));
g2d.draw(poly);
Вы также должны звонить super.paint(g)
прежде чем применить свою собственную картину...
Как примечание стороны, вы должны избегать переопределения paint
контейнеров верхнего уровня, таких как JApplet
, но вместо этого создайте пользовательский компонент, расширяющийся от чего-то вроде JPanel
и переопределить это paintComponent
метод, выполняя вашу собственную картину там (не забудьте позвонить super.paintComponent
). Посмотрите на Выполнение Custom Painting для более подробной информации
Вы также должны избегать использования KeyListener
и вместо этого используйте API связывания ключей, поскольку он не страдает от тех же проблем фокуса, которые KeyListener
делает...
Обновлен на работающем примере
Итак, я поиграл с кодом и создал этот простой пример...
В основном я выбросил 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
}
}
Это:
if (xpos < 0) {
означает "если курсор находится за пределами панели".
Это:
xpos = getX();
не получает координаты мыши.
Измените ваше событие на что-то вроде этого:
public void mouseMoved(MouseEvent e) {
xpos = e.getX();
if (xpos < getWidth() / 2) {
polyrot--;
} else {
polyrot++;
}
repaint();
}
Теперь он вращается против часовой стрелки, если курсор находится на левой стороне панели, и по часовой стрелке, если курсор находится на правой стороне.
Это:
g2d.draw(poly);
g2d.translate(width / 2, height / 2);
g2d.rotate(Math.toRadians(polyrot));
g2d.scale(5, 5);
не будет ничего делать, чтобы изменить изображение, потому что вы делаете свое преобразование после его рисования.
Это:
Graphics2D g2d = (Graphics2D) g;
это плохая идея, потому что вы применяете преобразования к глобальному графическому контексту, который будет применяться к последующим перерисовкам других компонентов.
Измените свою краску на что-то вроде этого:
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();
}
Дальнейшее чтение:
Отсюда:
public void mouseMoved(MouseEvent e){
xpos=getX();
if(xpos<0){polyrot--;}
else if(xpos>0){polyrot++;}
repaint();
break;
}
Кажется, вы обновляете только xpos. Вам следует также обновить переменную ypos. Возможно, вы захотите сделать это с чем-то вроде этого:
ypos=e.getY();
if (this.ypos<0){
this.polyrot--;
}else if (this.ypos>0) {
this.polyrot++;
}
this.repaint();