java - 棋盘游戏中如何移动跳棋棋子?

标签 java swing drag-and-drop

我使用 java 创建了一个西洋跳棋游戏界面,并将棋子放置在游戏板上的每个位置,但目前我无法将棋子从一个方格移动到另一个方格。

棋盘游戏中如何移动跳棋棋子? 以下是我尝试过的源代码:

    /*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package chackergame;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

/**
 *
 * @author wenda
 */
public class CheckerGame extends JFrame {

    
    private final int ROWS = 8;
    private final int COLL = 8;

    private final JPanel[][] square = new JPanel[8][8];
    private JPanel backgroundPanel;
    private final JLabel statusBar = new JLabel(" Red turn to play");
    private JLabel lbPieces = new JLabel();

    private boolean inDrag = false;
    
    public CheckerGame() {
        
        //Add a chess board to the Layered Pane 
        backgroundPanel = new JPanel();
        backgroundPanel.setLayout(new GridLayout(8, 8, 0, 0));
        
        add(backgroundPanel, BorderLayout.CENTER);
        add(statusBar, BorderLayout.SOUTH);

        
        createSquare();
        addPieces();
        
        setIconImage(PiecesIcon.iconGame.getImage());
        setTitle("Java Checkers");// set title game
        setSize(500, 500);
        
        //setResizable(false);
        setLocationRelativeTo(null);
        setLocationByPlatform(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
        
    }

    public void createSquare() {
        for (int row = 0; row < ROWS; row++) {
            for (int col = 0; col < COLL; col++) {

                JPanel cell = new JPanel();
                if ((row + col) % 2 == 1) {
                    cell.setBackground(new Color(99, 164, 54));
                    // cell.setBackground(Color.BLACK);
                }

                if ((row + col) % 2 == 0) {
                    cell.setBackground(new Color(247, 235, 164));
                    // cell.setBackground(Color.WHITE);
                }
                square[row][col] = cell;
                backgroundPanel.add(square[row][col]);
            }
        }
    }

    /**
     * Add pieces to the board
     */
    private void addPieces() {

        for (int row = 0; row < ROWS; row++) {
            for (int col = 0; col < COLL; col++) {

                lbPieces = new JLabel();
                lbPieces.setHorizontalAlignment(SwingConstants.CENTER);
                //lb.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1));

                if ((row + col) % 2 == 1) {
                    if (row < 3) {
                        lbPieces.setIcon(PiecesIcon.redPiece);
                    } else if (row > 4) {
                        lbPieces.setIcon(PiecesIcon.whitePiece);
                    }
                }

                square[row][col].setLayout(new BorderLayout());
                square[row][col].add(lbPieces, BorderLayout.CENTER);
            } // end of for col loop
        } // end of for row loop
    } // end of addPieces method 

    public class MouseInput extends MouseAdapter {


        @Override
        public void mousePressed(MouseEvent evt) {
        }

        @Override
        public void mouseReleased(MouseEvent evt) {
            
        }

        @Override
        public void mouseClicked(MouseEvent evt) {

        }

        @Override
        public void mouseDragged(MouseEvent evt) {
            
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        new CheckerGame();
    }

}

最佳答案

基本问题是将组件(在本例中为 JLable)从任何源容器(JPanel)拖动到任何其他容器。
每个这样的容器都可以是拖动组件的源或其放置目标。所以它需要同时支持两者。此类 JPanel 在以下 DragDropPane 类中实现。
为了编写这段代码,我借用了 MadProgrammer's answer它显示了一个源和一个目标的解决方案。
这是一个单文件 mre :可以将整个代码复制粘贴到LabelDnD.java文件中,然后运行。它演示了将 JLabel 从一个面板拖动到另一个面板。请注意评论:

import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDropEvent;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class LabelDnD{

    private static final int ROWS = 5, COLS = 5, GAP = 4;

    private Component makeContent() {

        JPanel content = new JPanel(new GridLayout(ROWS,COLS, GAP,GAP));
        content.setBorder(BorderFactory.createLineBorder(content.getBackground(), GAP));

        for(int i = 0; i < ROWS*COLS ; i++){
            content.add(new DragDropPane(String.valueOf(i)));
        }
        return content;
    }

    public static void main(String[] args) {

        SwingUtilities.invokeLater(() -> {
            JFrame f = new JFrame("Label Drag & Drop");
            f.add(new LabelDnD().makeContent());
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setLocationRelativeTo(null);
            f.pack();
            f.setVisible(true);
        });
    }
}

class DragDropPane extends JPanel implements DragGestureListener, DragSourceListener {

    private static final int W = 50, H = 50;
    private JComponent dragable;

    public DragDropPane(String text) {

        setBackground(Color.white);
        setPreferredSize(new Dimension(W, H));
        setBorder(BorderFactory.createLineBorder(Color.blue, 1));
        var label = new JLabel(text, JLabel.CENTER);
        setContent(label);
        new MyDropTargetListener(this);
        DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
                                        this, DnDConstants.ACTION_COPY, this);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(W, H);
    }

    public void setContent(JComponent component) {

        removeAll();
        dragable = component;
        add(component);
        repaint();
    }

    //-->DragGestureListener implementation

    @Override
    public void dragGestureRecognized(DragGestureEvent dge) {

        // Create our transferable wrapper
        Transferable transferable = new TransferableComponent(dragable);

        // Start the "drag" process...
        DragSource ds = dge.getDragSource();
        ds.startDrag(dge, Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR), transferable, this);
        remove(dragable);
        revalidate(); repaint();
    }

    //-->DragSourceListener implementation

    @Override
    public void dragEnter(DragSourceDragEvent dsde) {}

    @Override
    public void dragOver(DragSourceDragEvent dsde) {}

    @Override
    public void dropActionChanged(DragSourceDragEvent dsde) {}


    @Override
    public void dragExit(DragSourceEvent dse) {}

    @Override
    public void dragDropEnd(DragSourceDropEvent dsde) {
        // If the drop was not successful, we need to
        // return the component back to it's previous
        // parent
        if (!dsde.getDropSuccess()) {
            setContent(dragable);
        }
    }
}

class MyDropTargetListener extends DropTargetAdapter {

    private final DragDropPane target;

    public MyDropTargetListener(DragDropPane target) {
        this.target = target;
        new DropTarget(target, DnDConstants.ACTION_COPY, this, true, null);
    }

    @Override
    public void drop(DropTargetDropEvent event) {

        try {

            var tr = event.getTransferable();
            var component = (JComponent) tr.getTransferData(TransferableComponent.component);

            if (event.isDataFlavorSupported(TransferableComponent.component)) {

                event.acceptDrop(DnDConstants.ACTION_COPY);
                target.setContent(component);
                event.dropComplete(true);

            } else {
                event.rejectDrop();
            }

        } catch (Exception e) {
            e.printStackTrace();
            event.rejectDrop();
        }
    }
}

class TransferableComponent implements Transferable {

    protected static final DataFlavor component =
            new DataFlavor(JComponent.class, "A Component");

    protected static final DataFlavor[] supportedFlavors = {
            component
    };

    private final JComponent componentToTransfer;

    public TransferableComponent(JComponent componentToTransfer) {

        this.componentToTransfer = componentToTransfer;
    }

    @Override
    public DataFlavor[] getTransferDataFlavors() {

        return supportedFlavors;
    }

    @Override
    public boolean isDataFlavorSupported(DataFlavor flavor) {

        return flavor.equals(component);
    }

    @Override
    public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {

        if (flavor.equals(component)) return componentToTransfer;
        else  throw new UnsupportedFlavorException(flavor);
    }
}
<小时/>

enter image description here

关于java - 棋盘游戏中如何移动跳棋棋子?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57684613/

相关文章:

java - OpenApi 文档与 spring-doc 结合 ResponseBodyAdvice

java - 如何使用 JFileChooser.showSaveDialog(...) 设置建议的文件名?

javascript - HTML5 拖放 - 仅适用于每个拖放区的项目

java - 从 Java 中的字符串中删除模式

java - NETBEANS - 如何使单选按钮与背景图像匹配

java - Java从txt文件中读取数据,使用特定字符作为每次迭代的结束点

java - 如何获得更新后的排序后 TableModel?

java - 如何将 JScrollPane 调整为其包含的 JTree

javascript - Chrome 扩展程序 : can detect drag&drop in address bar?

java - 仅此网站无法拖放 Selenium