按下鼠标时更改mouseListener [英] Change mouseListener while mouse is pressed

查看:100
本文介绍了按下鼠标时更改mouseListener的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Java开发游戏并遇到以下挑战。

I'm working on a game in Java and have the following challenge.

我有2 JPanels 并且需要在视觉上将形状从一个 JPanel 拖到另一个。我使用 JFrame 中的 GlassPane 工作了。当我按下鼠标拖动形状时, GlassPane 激活并将形状传递给glassPane。因此,您需要将 JPAnels mouseAdapter 中的 mousePressed 状态转移到 glassPanes mouseAdapter 。我通过使用Robot类来解决这个问题,它在glaPate被激活后模拟了另一个 mousePressed 事件。

I have 2 JPanels and need to visually drag shapes from one JPanel to another. I've got this working using the GlassPane from the JFrame. When I press the mouse to drag a shape, the GlassPane activates and transfers the shape to the glassPane. Because of this you need to transfer the mousePressed state from the JPanels mouseAdapter to the glassPanes mouseAdapter. I solved this by using the Robot Class which simulates another mousePressed event after the glassPane has been acivated.

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

Now here comes the problem, this workaround only works on windows and not on mac osx, on osx the mouse keeps talking to the JPanels mouseAdapter as long as the mousebutton is pressed. So does anyone know how to transfer the mousePressed state from one mouseAdapter to another while pressing the mousebutton, in a proper way? (Releasing the button and pressing it again is not an option as this would defeat the purpose of dragging.)

推荐答案

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

Why not add the MouseListener just to the glasspane, and in the mousePressed method, get the mouse's location (Point) and then get the draggable component by calling getComponentAt(Point p) on the Container that holds your Component? You can then place the component into the glasspane and drag it there. For instance here is one way I've done this using a JLayeredPane (which is similar to using a glasspane): DragLabelOnLayeredPane

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

Or another thought: why not simply add the MouseAdapter on the dragged component itself and leave it on the component? As long as you take care to get mouse position relative to the screen and move the component relative to its container, you should have no problem whether the component is in the contentPane or the glasspane.

编辑:或者选择MeBigFatGuy的优秀建议。

edit: or go with MeBigFatGuy's excellent suggestion.

编辑2:深夜半醉的尝试尝试一个不简短的建议类似概念证明程序,一种通过仅将MouseListener添加到玻璃窗格来移动形状的程序。

edit 2: A semi-drunk late at night attempt at a not-brief-as-I'd-like proof of concept program, a program that moves shapes by adding a MouseListener to the glass pane only.

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);
   }
}

这篇关于按下鼠标时更改mouseListener的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆