2013-07-15 46 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