2013-07-15 45 views
1

我目前正在尝试为一款名为Carcassone的游戏创建应用程序,但我在使用JLayeredPane和MouseAdapters时遇到了问题。JLayeredPane和MouseAdapter问题

目前我有一个JLayeredPane,它包含一个带GridLayout的JPanel作为游戏板。 GridLayout的每个单元格都包含一个JPanel,其中包含一个JLabel,用于表示贴图中的贴图。 (一个空的瓦片只是一个带黑色方块的JLabel作为图像)。

我向JLayeredPane添加了一个自定义鼠标适配器(TileMouseAdapter),它允许用户在游戏板周围移动瓷砖(鼠标按下 - 拖拽 - 释放)或旋转瓷砖(鼠标点击)。 (要测试点击下一个平铺按钮并在显示的平铺中移动,点击提交按钮后,如果平铺是有效移动,平铺将不再可拖动)。这一切都完美,因为它应该直到我添加下一部分。

现在我想添加一个单独的JPanel到屏幕顶部的JLayeredPane。本部分应该包含玩家可以放在瓷砖上的游戏片段。我也希望JPanel能够保留游戏棋子,以便玩家可以将棋子拖动到棋子上。但是,当我创建此面板并将其添加到JLayeredPane时,上一节中的鼠标适配器不再正常工作。例如,如果您单击平铺的底部部分,则不再识别您正在点击平铺。如果你点击每个瓦片的上半部分,它将只会选择瓦片。此外,如果你点击一个瓷砖的底部,有时它会选择下面的瓷砖。即看起来好像选择平铺的机制似乎向上移动大约一半的平铺。 任何人都可以找出解决这个问题/一个可能的解决办法吗? 谢谢!

下面的代码,是我用于创建包含JPanel中的板(myBoardPanel)以及为游戏片面板JLayeredPane的代码(makeMeeplePanel())

 private JLayeredPane makeBoardPanel() { 
    JLayeredPane layeredPane = new JLayeredPane(); 
    layeredPane.setLayout(new BorderLayout()); 
    myBoardPanel = new CarcassoneBoardPanel(layeredPane); 
    layeredPane.add(makeMeeplePanel(), BorderLayout.NORTH, JLayeredPane.DEFAULT_LAYER); 
    layeredPane.add(myBoardPanel, BorderLayout.CENTER, JLayeredPane.DEFAULT_LAYER); 

    TileMouseAdapter tileMouseAdapter = new TileMouseAdapter(layeredPane); 
    //MeepleMouseAdapter meepleMouseAdapter = new MeepleMouseAdapter(layeredPane); 

    layeredPane.addMouseListener(tileMouseAdapter); 
    layeredPane.addMouseMotionListener(tileMouseAdapter); 
    //layeredPane.addMouseListener(meepleMouseAdapter); 
    //layeredPane.addMouseMotionListener(meepleMouseAdapter); 
    return layeredPane; 
} 

这是我的自定义鼠标适配器的游戏板:

package gui; 
    import java.awt.Component; 
    import java.awt.event.MouseAdapter; 
    import java.awt.event.MouseEvent; 
    import javax.swing.JLayeredPane; 
    import javax.swing.JPanel; 

    import tiles.*; 

    public class TileMouseAdapter extends MouseAdapter { 
private JLayeredPane myLayeredPane; 
private CarcassoneBoardPanel myBoard; 
private Tile dragLabel; 
private JPanel clickedPanel; 


public TileMouseAdapter(JLayeredPane layeredPane) { 
    myLayeredPane = layeredPane; 
    myBoard = (CarcassoneBoardPanel) layeredPane.getComponents()[1]; 
} 

private void reset() { 
    if (dragLabel != null) { 
     myLayeredPane.remove(dragLabel); 
     myLayeredPane.revalidate(); 
     myLayeredPane.repaint(); 
    } 
    dragLabel = null; 
    clickedPanel = null; 
} 

@Override 
public void mouseClicked(MouseEvent event) { 
    clickedPanel = (JPanel) myBoard.getComponentAt(event.getPoint()); 
    if (clickedPanel == null) { 
     reset(); 
     return; 
    } 
    Component[] components = clickedPanel.getComponents(); 
    if (!(components[0] instanceof Tile) || components[0] instanceof EmptyTile || !((Tile) components[0]).isDraggable()) { 
     return; 
    } 

    dragLabel = (Tile) components[0]; 
    dragLabel.rotate(); 
    clickedPanel.revalidate(); 
    clickedPanel.repaint(); 
    reset(); 
} 

@Override 
public void mousePressed(MouseEvent event) { 
    clickedPanel = (JPanel) myBoard.getComponentAt(event.getPoint()); 
    System.out.println(event.getPoint()); 
    if (clickedPanel == null) { 
     reset(); 
     return; 
    } 
    Component[] components = clickedPanel.getComponents(); 
    if (!(components[0] instanceof Tile) || (components[0] instanceof EmptyTile) || !((Tile) components[0]).isDraggable()) { 
     return; 
    } 
    dragLabel = (Tile) components[0]; 
    clickedPanel.remove(dragLabel); 
    clickedPanel.add(new EmptyTile(dragLabel.getRow(), dragLabel.getCol())); 
    clickedPanel.revalidate(); 
    clickedPanel.repaint(); 

    int x = event.getPoint().x - dragLabel.getWidth()/2; 
    int y = event.getPoint().y - dragLabel.getHeight()/2; 
    dragLabel.setLocation(x, y); 
    try { 
     myLayeredPane.add(dragLabel, JLayeredPane.DRAG_LAYER); 
     myLayeredPane.repaint(); 
    } catch (IllegalArgumentException e) { 
     //TODO: deal with this? 
     //gives error for some unknown reason, but doesnt effect anything? ignore...dumb error cus jswing sucks 
    } 
} 

@Override 
public void mouseDragged(MouseEvent event) { 
    if (dragLabel == null) { 
     return; 
    } 
    int x = event.getPoint().x - dragLabel.getWidth()/2; 
    int y = event.getPoint().y - dragLabel.getHeight()/2; 
    dragLabel.setLocation(x, y); 
    myLayeredPane.revalidate(); 
} 

@Override 
public void mouseReleased(MouseEvent event) { 
    //TODO: make sure cannot place tile on already occupied panel... 
    if (dragLabel == null || !dragLabel.isDraggable()) { 
     return; 
    } 
    myLayeredPane.remove(dragLabel); 
    myLayeredPane.revalidate(); 
    myLayeredPane.repaint(); 


    JPanel droppedPanel = (JPanel) myBoard.getComponentAt(event.getPoint()); 
    if (droppedPanel == null) { 
     clickedPanel.removeAll(); 
     clickedPanel.add(dragLabel); 
     clickedPanel.revalidate(); 
     reset(); 
     return; 
    } 

    dragLabel.setPosition(((Tile) droppedPanel.getComponents()[0]).getRow(), ((Tile) droppedPanel.getComponents()[0]).getCol()); 
    droppedPanel.removeAll(); 
    droppedPanel.add(dragLabel); 
    droppedPanel.revalidate(); 
    reset(); 
} 

}

请让我知道如果你需要的信息了/代码。这是我第一次使用这个网站,很抱歉,如果我没有提供足够的解释,等等...... 谢谢!

回答

2

你的问题是在这里:

@Override 
public void mouseClicked(MouseEvent event) { 
    clickedPanel = (JPanel) myBoard.getComponentAt(event.getPoint()); 

event.getPoint()一个Point相对会回到你layeredPane与您的鼠标监听被注册。 myBoard.getComponentAt()将在相对于myBoard组件的点处返回组件,该组件在layeredPane.getComponents()[1]的分层窗格中。

+0

太棒了!那很简单......你修好了。谢谢你为我节省了很多时间! – nothingness