現在、Carcassone というゲームのアプリケーションを作成しようとしていますが、JLayeredPane を MouseAdapters と組み合わせて使用すると問題が発生します。
現在、ゲームボードとして機能する GridLayout を持つ JPanel を含む JLayeredPane があります。GridLayout の各セルには、ボード上に配置されるタイルを表す JLabel を内部に含む JPanel が含まれます。(空のタイルは、イメージとして黒い四角を持つ JLabel です)。
カスタム マウス アダプター (TileMouseAdapter) を JLayeredPane に追加しました。これにより、ユーザーはゲーム ボード上でタイルを移動したり (マウスを押してドラッグして放したり)、タイルを回転したり (マウス クリック) したりできます。(テストするには、[次のタイル] ボタンをクリックして、表示されるタイルを移動します。送信ボタンをクリックした後、それが有効な移動であった場合、タイルはドラッグできなくなります)。次の部分を追加するまで、これはすべて正常に機能します。
ここで、画面上部の JLayeredPane に個別の JPanel を追加したいと考えています。このセクションには、プレイヤーがタイルに配置できるゲーム ピースを保持する必要があります。また、プレイヤーがピースをタイルにドラッグできるように、JPanel にゲームのピースを保持させたいと考えています。ただし、このパネルを作成して JLayeredPane に追加すると、前のセクションのマウス アダプタが正しく機能しなくなります。たとえば、タイルの下部をクリックすると、タイルをクリックしていることを認識しなくなります。各タイルの上半分をクリックした場合にのみ、タイルが選択されます。また、タイルの下をクリックすると、下のタイルが選択される場合があります。つまり、タイルを選択するメカニズムが約半分のタイルだけ上方にシフトされているように見えます。誰でもこの問題の説明/可能な修正を理解できますか? ありがとう!
以下のコードは、ボード用の JPanel (myBoardPanel) とゲーム ピース用のパネル (makeMeeplePanel()) を含む JLayeredPane を作成するために使用したコードです。
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();
}
}
情報/コードが必要な場合はお知らせください。初めてこのサイトを利用するので、説明不足等ありましたら申し訳ありません…よろしくお願いします!