java - 按下鼠标时更改 mouseListener

标签 java mouse mouseevent awtrobot

我正在使用 Java 开发一款游戏,并面临以下挑战。

我有 2 个 JPanel,需要以可视方式将形状从一个 JPanel 拖动到另一个。我已经使用 JFrame 中的 GlassPane 完成了这项工作。当我按下鼠标拖动形状时,GlassPane 会激活并将形状传输到 glassPane。因此,您需要将 mousePressed 状态从 JPanels mouseAdapter 传输到 glassPanes mouseAdapter。我通过使用 Robot 类解决了这个问题,该类在 glassPane 激活后模拟另一个 mousePressed 事件。

现在问题来了,此解决方法仅适用于 Windows,不适用于 mac osx,在 osx 上,只要按下鼠标按钮,鼠标就会一直与 JPanels mouseAdapter 通信。那么有谁知道如何在按下鼠标按钮时以正确的方式将 mousePressed 状态从一个 mouseAdapter 转移到另一个? (释放按钮并再次按下不是一个选项,因为这会破坏拖动的目的。)

最佳答案

为什么不只将 MouseListener 添加到 glasspane,并在 mousePressed 方法中获取鼠标的位置(Point),然后通过在保存组件的容器上调用 getComponentAt(Point p) 来获取可拖动组件?然后,您可以将组件放入玻璃板中并将其拖到那里。例如,这是我使用 JLayeredPane 完成此操作的一种方法(类似于使用玻璃板): DragLabelOnLayeredPane

或者另一个想法:为什么不简单地将 MouseAdapter 添加到拖动的组件本身上并将其保留在组件上?只要您注意获取鼠标相对于屏幕的位置并相对于其容器移动组件,无论该组件是在 contentPane 还是 glasspane 中,您都应该没有问题。

编辑:或者采纳 MeBigFatGuy 的极好建议。

编辑 2:深夜半醉尝试一个不简单的概念验证程序,该程序仅通过向玻璃 Pane 添加 MouseListener 来移动形状。

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.*;

@SuppressWarnings("serial")
public class DragShapesMainPanel extends JPanel {
   private static final Dimension RIGHT_PANEL_SIZE = new Dimension(300, 450);
   private static final int SHAPE_COUNT = 10;
   private static final int SHAPE_WIDTH = 40;
   private static final int SHAPE_HEIGHT = SHAPE_WIDTH;
   private Shape draggedShape = null;
   private DragShapesPanel leftPanel = new DragShapesPanel(Color.blue, Color.black);
   private DragShapesPanel rightPanel = new DragShapesPanel(Color.blue, Color.black);
   private DragShapesGlassPanel glassPanel = new DragShapesGlassPanel(Color.pink, Color.gray);
   private Random random = new Random();

   public DragShapesMainPanel() {
      setLayout(new GridLayout(1, 0));
      setBackground(Color.black);
      rightPanel.setPreferredSize(RIGHT_PANEL_SIZE);
      leftPanel.setPreferredSize(RIGHT_PANEL_SIZE);
      rightPanel.setBorder(BorderFactory.createLineBorder(Color.black, 1));
      leftPanel.setBorder(BorderFactory.createLineBorder(Color.black, 1));
      add(leftPanel);
      add(rightPanel);

      MouseAdapter myMouseAdapter = new MyMouseAdapter();
      glassPanel.addMouseListener(myMouseAdapter);
      glassPanel.addMouseMotionListener(myMouseAdapter);

      glassPanel.setOpaque(false);
      glassPanel.setVisible(true);

      for (int i = 0; i < SHAPE_COUNT; i++) {
         leftPanel.addShape(createRandomShape(i));
      }
   }

   private Shape createRandomShape(int i) {
      Dimension size = rightPanel.getPreferredSize();
      int x = random.nextInt(size.width - SHAPE_WIDTH);
      int y = random.nextInt(size.height - SHAPE_HEIGHT);
      switch (i % 3) {
      case 0:
         return new Ellipse2D.Double(x, y, SHAPE_WIDTH, SHAPE_HEIGHT);

      case 1:
         return new Rectangle2D.Double(x, y, SHAPE_WIDTH, SHAPE_HEIGHT);

      case 2:
         return new RoundRectangle2D.Double(x, y, SHAPE_WIDTH, SHAPE_HEIGHT, 15, 15);

      default:
         break;
      }
      return null;
   }

   public JPanel getGlassPanel() {
      return glassPanel;
   }

   private class MyMouseAdapter extends MouseAdapter {
      Point initialLocation = null;

      @Override
      public void mousePressed(MouseEvent e) {
         if (e.getButton() != MouseEvent.BUTTON1) {
            return;
         }
         Component componentAt = getComponentAt(e.getPoint());
         if (!(componentAt instanceof DragShapesPanel)) {
            return;
         }

         initialLocation = e.getPoint();
         DragShapesPanel dsPanel = (DragShapesPanel) getComponentAt(initialLocation);

         int x = initialLocation.x - dsPanel.getLocation().x;
         int y = initialLocation.y - dsPanel.getLocation().y;
         Point p = new Point(x, y);

         Shape shape = dsPanel.getShapeAtPoint(p);
         if (shape == null) {
            initialLocation = null;
            return;
         }

         dsPanel.removeShape(shape);
         dsPanel.repaint();

         int tx = dsPanel.getLocation().x;
         int ty = dsPanel.getLocation().y;
         draggedShape = AffineTransform.getTranslateInstance(tx, ty).createTransformedShape(shape);

         glassPanel.setShape(draggedShape);
         glassPanel.repaint();
      }

      @Override
      public void mouseDragged(MouseEvent e) {
         if (initialLocation == null) {
            return;
         }

         Point currentLocation = e.getPoint();
         int x = currentLocation.x - initialLocation.x;
         int y = currentLocation.y - initialLocation.y;

         glassPanel.translate(new Point(x, y));
         glassPanel.repaint();
      }

      @Override
      public void mouseReleased(final MouseEvent e) {
         if (initialLocation == null) {
            return;
         }
         SwingUtilities.invokeLater(new Runnable() {
            public void run() {
               Component componentAt = getComponentAt(e.getPoint());
               if (!(componentAt instanceof DragShapesPanel)) {
                  return;
               }

               DragShapesPanel dsPanel = (DragShapesPanel) getComponentAt(e.getPoint());

               Point currentLocation = e.getPoint();
               int x = currentLocation.x - initialLocation.x;
               int y = currentLocation.y - initialLocation.y;

               Point dspPoint = dsPanel.getLocation();
               int tx = x - dspPoint.x;
               int ty = y - dspPoint.y;
               draggedShape = AffineTransform.getTranslateInstance(tx, ty).createTransformedShape(
                        draggedShape);

               dsPanel.addShape(draggedShape);
               dsPanel.repaint();

               initialLocation = null;
               glassPanel.setShape(null);
               glassPanel.translate(new Point(0, 0));
            }
         });
      }
   }

   private static void createAndShowUI() {
      DragShapesMainPanel dragShapesMain = new DragShapesMainPanel();
      JFrame frame = new JFrame("DragShapes");
      frame.getContentPane().add(dragShapesMain);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setGlassPane(dragShapesMain.getGlassPanel());
      frame.getGlassPane().setVisible(true);
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }
}

@SuppressWarnings("serial")
class DragShapesPanel extends JPanel {
   private static final float STROKE_WIDTH = 3;
   private static final Stroke SHAPE_STROKE = new BasicStroke(STROKE_WIDTH);
   private List<Shape> shapeList = new ArrayList<Shape>();
   private Color shapeFillColor;
   private Color shapeBorderColor;

   public DragShapesPanel(Color fillColor, Color borderColor) {
      this.shapeFillColor = fillColor;
      this.shapeBorderColor = borderColor;
   }

   public void addShape(Shape s) {
      shapeList.add(s);
   }

   public void removeShape(Shape s) {
      shapeList.remove(s);
   }

   public Shape getShapeAtPoint(Point p) {
      Shape shapeAtPoint = null;
      for (int i = shapeList.size() - 1; i >= 0; i--) {
         if (shapeList.get(i).contains(p)) {
            return shapeList.get(i);
         }
      }
      return shapeAtPoint;
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      for (Shape shape : shapeList) {
         g2.setColor(shapeFillColor);
         g2.fill(shape);
         g2.setStroke(SHAPE_STROKE);
         g2.setColor(shapeBorderColor);
         g2.draw(shape);
      }
   }
}

@SuppressWarnings("serial")
class DragShapesGlassPanel extends JPanel {
   private static final float STROKE_WIDTH = 1.5f;
   private static final Stroke SHAPE_STROKE = new BasicStroke(STROKE_WIDTH);
   private Shape shape = null;
   private Color shapeFillColor;
   private Color shapeBorderColor;
   private AffineTransform transform = new AffineTransform();

   public DragShapesGlassPanel(Color fillColor, Color borderColor) {
      this.shapeFillColor = fillColor;
      this.shapeBorderColor = borderColor;
   }

   public void setShape(Shape shape) {
      this.shape = shape;
   }

   public void translate(Point p) {
      transform = AffineTransform.getTranslateInstance(p.x, p.y);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (shape == null) {
         return;
      }
      Graphics2D g2 = (Graphics2D) g;
      g2.transform(transform);
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setColor(shapeFillColor);
      g2.fill(shape);
      g2.setStroke(SHAPE_STROKE);
      g2.setColor(shapeBorderColor);
      g2.draw(shape);
   }
}

关于java - 按下鼠标时更改 mouseListener,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5601010/

相关文章:

wpf - 在 wpf 中启用禁用的文本框

objective-c - 全局鼠标事件和全屏应用程序

java - 让JScrollPane在JList里面改变的时候显示滚动条

java - Eclipse中的多IDE调试

java - 使用 java programmig 读取 Ubuntu 14.04 鼠标事件文件 (/dev/input/event3) 时出错

c++ - SetWindowsHookEx WH_MOUSE_LL Hook 只需要 1 次鼠标移动

c# - WPF:点击用户控件背景不触发

java - 从json字符串中提取对象数组并将它们放入ArrayList中?

java - Cucumber-jvm功能文件和步骤定义文件实现问题

Java:如何保存MouseButton状态?