如何使用MouseListener在网格中查找特定单元格

问题描述:

我正尝试使用由单元格组成的10 x 10网格创建Java游戏。 网格看起来链接才可这样的:如何使用MouseListener在网格中查找特定单元格

public class Grid extends JPanel implements MouseListener { 
    public static final int GRID_SIZE = 10; 

    public Grid() { 
     setPreferredSize(new Dimension(300, 300)); 
     setLayout(new GridLayout(GRID_SIZE, GRID_SIZE)); 

     for (int x = 0; x < GRID_SIZE; x++) 
      for (int y = 0; y < GRID_SIZE; y++) 
       add(new Cell(x, y)); 
     addMouseListener(this); 
    } 

// All Mouse Listener methods are in here. 

Cell类看起来是这样的:

public class Cell extends JPanel { 

    public static final int CELL_SIZE = 1; 
    private int xPos; 
    private int yPos; 

    public Cell (int x, int y) { 
     xPos = x; 
     yPos = y; 
     setOpaque(true); 
     setBorder(BorderFactory.createBevelBorder(CELL_SIZE)); 
     setBackground(new Color(105, 120, 105)); 
     setPreferredSize(new Dimension(CELL_SIZE, CELL_SIZE)); 
    } 

    // Getter methods for x and y. 

我的问题是,我现在想实现在网格类的MouseListeners。我已经意识到,虽然我可以返回网格的X和Y坐标,但我似乎无法操纵单元格本身。 我假设这是因为当我在网格中创建它们时,我创建了100个没有标识符的随机单元格,因此我无法直接访问它们。

有人可以给我这方面的建议吗?我是否需要检修我的代码以及创建单元格的方式?我是非常愚蠢的,错过了一个明显的访问方式吗? 谢谢

您可以使用适配器模式,如下所示。这样,您可以将侦听器单独添加到每个网格单元,但仍然可以处理来自Grid的事件。

请注意,Grid不再实现MouseListener,这是由细胞现在处理。

public class Grid extends JPanel { 
    public static final int GRID_SIZE = 10; 

    public Grid() { 
     setPreferredSize(new Dimension(300, 300)); 
     setLayout(new GridLayout(GRID_SIZE, GRID_SIZE)); 

     for (int x = 0; x < GRID_SIZE; x++) { 
      for (int y = 0; y < GRID_SIZE; y++) { 
       final Cell cell = new Cell(x, y); 
       add(cell); 
       cell.addMouseListener(new MouseListener() { 
        public void mouseClicked(MouseEvent e) { 
         click(e, cell); 
        } 
        // other mouse listener functions 
       }); 
      } 
     }   
    } 

    public void click(MouseEvent e, Cell cell) { 
     // handle the event, for instance 
     cell.setBackground(Color.blue); 
    } 

    // handlers for the other mouse events 
} 

子类可以覆盖此为:

public class EnemyGrid extends Grid { 
    public void click(MouseEvent e, Cell cell) { 
     cell.setBackground(Color.red); 
    } 
} 
+0

这是一段非常有用的代码 - 谢谢!我可以问一个后续问题 - 我实际上从Grid创建两个子类:OwnGrid和EnemyGrid。它们最初都覆盖了Grid类中包含的MouseListener方法。 用你提出的新结构,我怎么能在网格子类中重写这些方法? – 2013-04-24 13:23:21

+0

@AndrewMartin我不知道我是否理解正确,但如果你想在两个子类中处理不同的事件,你可以重写'mouseClicked(MouseEvent e,Cell cell)' – 2013-04-24 13:28:23

+0

'我怎么能重写这些方法Grid子类不是不容易的工作(因为没有任何问题是可能的),你可以丢失在JCOmponents层次结构中,其中一个缺点来自继承,[使用合成代替](http://www.javaworld.com/ jw-11-1998/jw-11-techniques.html) – mKorbel 2013-04-24 13:33:42

+0

感谢您的回答,并对其他帖子发表评论。我对构图不是很熟悉。我已经摆脱了子类的“扩展”部分,而是创建完成“私人网格网格=新的网格()” - 我现在怎么连接到mouseListeners等? – 2013-04-24 13:37:26

+0

[see another JButton and ActionListener](http://stackoverflow.com/a/9007348/714968),再次将JButton更改为JPanel和ActionListener为MouseListener,作为一般和工作代码示例 – mKorbel 2013-04-24 13:41:36

+0

我建议使用putClientProperty基于网格的游戏例如益智,数独,...。 – mKorbel 2013-04-24 13:46:13

最明显的办法是将你的MouseListenerCell类本身。

我想到的第二个选项是使用java.awt.Container.getComponentAt(int, int)

+0

或SwingUtilities – mKorbel 2013-04-24 16:34:19