java - JLayeredPane 和 MouseAdapter 问题

标签 java swing jlayeredpane mouse-listeners

我目前正在尝试为名为 Carcassone 的游戏创建应用程序,但在将 JLayeredPane 与 MouseAdapters 结合使用时遇到问题。

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

我在 JLayeredPane 中添加了一个自定义鼠标适配器 (TileMouseAdapter),它允许用户在游戏板周围移动图 block (鼠标按下 - 拖动 - 释放)或旋转图 block (鼠标单击)。 (要测试,请单击下一个图 block 按钮并在出现的图 block 周围移动,单击提交按钮后,如果移动有效,则图 block 将不再可拖动)。这一切都完美地工作,直到我添加下一部分。

现在我想向屏幕顶部的 JLayeredPane 添加一个单独的 JPanel。该部分应放置玩家可以放置在图 block 上的游戏棋子。我还希望 JPanel 能够容纳游戏棋子,以便玩家可以将棋子拖到图 block 上。但是,当我创建此面板并将其添加到 JLayeredPane 时,上一节中的鼠标适配器不再正常工作。例如,如果您单击图 block 的底部部分,它不再识别您正在单击该图 block 。仅当您单击每个图 block 的上半部分时,它才会选择该图 block 。此外,如果您单击某个图 block 的底部,有时它会选择下面的图 block 。也就是说,选择图 block 的机制似乎向上移动了大约半个图 block 。 任何人都可以找出这个问题的解释/可能的解决方案吗? 谢谢!

下面的代码是我用来创建 JLayeredPane 的代码,其中包含棋盘的 JPanel (myBoardPanel) 以及游戏件的面板 (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();
}

}

如果您需要更多信息/代码,请告诉我。这是我第一次使用这个网站,如果我没有提供足够的解释等,我很抱歉...... 谢谢!

最佳答案

您的问题在这里:

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

event.getPoint() 将返回一个与注册鼠标监听器的 layeredPane 相关的 PointmyBoard.getComponentAt() 将返回相对于 myBoard 组件的位置的组件,该组件位于分层 Pane 中的 layeredPane.getComponents()[1] .

关于java - JLayeredPane 和 MouseAdapter 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17655179/

相关文章:

Java Swing 混合 Pane

java - 带有 LayoutManager 的 JLayeredPane

java - Hibernate 无法执行查询 getInt() 的值无效

java - 在JavaFX应用程序上运行Proguard后出现NoClassDefFoundError

java - Web 界面或图形用户界面

java - JButton "disappears"尽管它位于 JLabel 之外的另一层

java - ListView点击事件(扩展ListActivity)

java - JDK 11 : java. lang.NoClassDefFoundError:javax/xml/ws/handler/soap/SOAPHandler

java - 属性集构造

java - 使用 Apache Commons Configuration 将用户输入的路径传递到 .properties 文件中