2011-04-08 168 views
1

我正在使用Java進行遊戲並遇到以下挑戰。按住鼠標按鈕時更改mouseListener

我有2 JPanels,並需要從一個JPanel視覺拖動形狀到另一個。我使用JFrameGlassPane這個工作。當我按下鼠標拖動一個形狀時,GlassPane激活並將形狀轉移到glassPane。因此,您需要將mousePressed狀態從JPanels mouseAdapter轉移到glassPanes mouseAdapter。我通過使用機器人類來解決這個問題,該機器人類在glassPane被激活後模擬另一個mousePressed事件。

現在問題來了,這個解決方法只適用於windows,而不是osx上的osx上,只要鼠標按鈕被按下,鼠標一直跟JPanels mouseAdapter對話。那麼是否有人知道如何以正確的方式將mousePressed狀態從一個mouseAdapter轉移到另一個狀態,同時按下鼠標按鈕? (釋放按鈕並再次按下不是一個選項,因爲這會拖拽拖拽的目的。)

+1

它似乎是你試圖重新實現Java的拖放機制。你嘗試過使用它嗎? – MeBigFatGuy 2011-04-08 21:42:33

+0

@MeBigFatGuy那麼,形狀不支持開箱即用,所以我需要實現它,這將是很多工作。 (特別是因爲我不知道該怎麼做)而且我已經投入了相當多的時間在這種拖動方法中,所以我不願放棄它... – Jesse 2011-04-08 21:54:39

+0

瞭解。但我猜測把你的形狀變成組件會比較容易,然後試着跳過你試圖做的事情。祝你好運! – MeBigFatGuy 2011-04-08 22:08:56

回答

2

爲什麼不將MouseListener添加到glasspane中,並在mousePressed方法中獲取鼠標的位置(Point)和然後通過調用持有組件的Container的getComponentAt(Point p)來獲取可拖動的組件?然後,您可以將組件放入玻璃窗內並將其拖動到那裏。例如,這裏是我使用JLayeredPane(類似於使用玻璃窗)完成此操作的一種方式:DragLabelOnLayeredPane

或者另一種想法:爲什麼不簡單地將MouseAdapter添加到拖動組件本身並將其留在組件上?只要您注意鼠標相對於屏幕的位置並將組件相對於其容器移動,無論組件位於contentPane還是glasspane中,都應該沒有問題。

編輯:或去與MeBigFatGuy的優秀建議。

編輯2:在深夜嘗試一個半簡化的概念程序,這是一個通過向Glass面板添加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); 
    } 
} 
+0

這是你有的一個有趣的想法,我會嘗試一下。日Thnx。 – Jesse 2011-04-08 22:17:41

+0

你不能添加mouseListeners到Shape對象,有什麼建議嗎? – Jesse 2011-04-08 23:56:37

+0

@Jesse:創建併發布[SSCCE](http://sscce.org),讓您獲得快速獲得體面的幫助的最佳機會(查看鏈接)。 – 2011-04-09 02:40:44