如何确保在 Java Swing 中以编程方式删除棋子后,视觉上将棋子从屏幕上删除?

问题描述 投票:0回答:1

我使用 Java Swing 实现了一个国际象棋游戏,我面临一个问题,即使以编程方式从棋盘上删除棋子后,其视觉表示仍保留在屏幕上。我已检查保存碎片的数据结构是否已正确更新,但视觉表示并未反映此更改。如何确保以编程方式删除棋子时,棋子的视觉表示也从屏幕上删除?

public static <K, V> K getKeyFromValue(Map<K, V> map, V value) {
        for (Map.Entry<K, V> entry : map.entrySet()) {
            if (Objects.equals(value, entry.getValue())) {
                return entry.getKey();
            }
        }
        return null;
    }

public void deleteChessPiece(ChessPiece piece) {
    if (piece != null) {
        String key = getKeyFromValue(pieceBox, piece);
        if (key != null) {
            System.out.println(key);
            pieceBox.remove(key);
            pieceLabels.remove(key);
            JLabel label = pieceLabels.get(key);
            if (label != null) {
                remove(label); 
            }
        }
    }
    invalidate();
    revalidate();
    repaint();
}

还有:

package com.wallhack.chess;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import javax.swing.JLabel;

public class Board extends JPanel {
    private final PieceFactory pieceFactory = new PieceFactory();
    public ConcurrentHashMap<String, ChessPiece> pieceBox = new ConcurrentHashMap<>();
    public HashMap<String, JLabel> pieceLabels = new HashMap<>();
    private final int cellSize = 80;
    private final int initialX = 63;
    private final int initialY = 60;
    private final BoardRender boardRender;
    private final BoardLayoutManager boardLayoutManager;
    private Point highlightCell;

    public Board(BoardLayoutManager boardLayoutManager) {
        this.boardLayoutManager = boardLayoutManager;
        setLayout(new BoardLayoutManager());

        boardRender = new BoardRender(initialX, initialY, cellSize);

        pieceByDefault();

        for (String piece : pieceBox.keySet()) {
            createAndPositionLabel(piece);
        }

        for (String piece : pieceLabels.keySet()) {
            JLabel label = pieceLabels.get(piece);
            ChessPiece chessPiece = pieceBox.get(piece);
            if (label != null && chessPiece != null) {
                Point pieceCoordinates = new Point(chessPiece.getCoordinates().x, chessPiece.getCoordinates().y);
                add(label , pieceCoordinates);
            }
        }


        MouseHandler mouseHandler = new MouseHandler(this, new PieceMoves(this));
        addMouseListener(mouseHandler);
        addMouseMotionListener(mouseHandler);

    }
    public static <K, V> K getKeyFromValue(Map<K, V> map, V value) {
        for (Map.Entry<K, V> entry : map.entrySet()) {
            if (Objects.equals(value, entry.getValue())) {
                return entry.getKey();
            }
        }
        return null;
    }
    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D) g;
        boardRender.drawBoard(g2);
        boardRender.drawLabel(g2);

        if (highlightCell != null) {
            Point cell = gridToPoint(highlightCell);
            Rectangle bounds = new Rectangle(cell.x, cell.y, cellSize,cellSize);
            g2.setColor(Color.RED);
            g2.draw(bounds);
        }
    }

    private void createAndPositionLabel(String piece) {
        JLabel label = new JLabel();

        try {
            String imagePath = "com/wallhack/chess/resources/" + pieceBox.get(piece).getIndex();
            label.setIcon(new ImageIcon(ImageIO.read(Objects.requireNonNull(getClass().getClassLoader().getResource(imagePath)))));

        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Eroare la citirea imaginii!");
        }

        Point offset = getBoardOffset();
        Point pieceCoordinates = gridToPoint(pieceBox.get(piece).getCoordinates());
        label.setBounds(pieceCoordinates.x + offset.x, pieceCoordinates.y + offset.y, cellSize, cellSize);

        pieceLabels.put(piece, label);
    }

    private void pieceByDefault () {
        String[][] defaultPositions = {
                {"Br1", "Bn1", "Bb1", "Bq", "Bk", "Bb2", "Bn2", "Br2"},
                {"Bp1", "Bp2", "Bp3", "Bp4", "Bp5", "Bp6", "Bp7", "Bp8"},
                {" ", " ", " ", " ", " ", " ", " ", " "},
                {" ", " ", " ", " ", " ", " ", " ", " "},
                {" ", " ", " ", " ", " ", " ", " ", " "},
                {" ", " ", " ", " ", " ", " ", " ", " "},
                {"LP1", "LP2", "LP3", "LP4", "LP5", "LP6", "LP7", "LP8"},
                {"LR1", "LN1", "LB1", "LQ", "LK", "LB2", "LN2", "LR2"}
        };
        for (int i = 0; i < defaultPositions.length; i++) {
            for (int j = 0; j < defaultPositions.length; j++) {
                String pieceType = defaultPositions[i][j];
                if (!pieceType.equals(" ")) {
                    pieceBox.put(pieceType, pieceFactory.create(pieceType.charAt(1), new Point(j, i)));
                }
            }
        }
    }

    public Point pointToGrid(Point p) {
        Point point = null;
        if (p != null) {
            var pointX = (p.x - initialX) / cellSize;
            var pointY = (p.y - initialY) / cellSize;
            if (0 <= pointX && pointX <= 7 && 0 <= pointY && pointY <= 7){
                point = new Point(pointX, pointY);
            }
        }
        return point;
    }
    public Point gridToPoint(Point grid) {
        Point p = new Point();
        if (grid != null) {
            p.x = grid.x * cellSize + initialX;
            p.y = grid.y * cellSize + initialY;
        }
        return p;
    }

    public void setPieceGrid(Component comp, Point grid) {
        ((BoardLayoutManager) getLayout()).setPieceGrid(comp, grid);
        invalidate();
        revalidate();
        repaint();
    }

//    public void deleteChessPiece(ChessPiece piece) {
//        if (piece != null) {
//            String key = getKeyFromValue(pieceBox, piece);
//            if (key != null) {
//                System.out.println(key);
//                pieceBox.remove(key);
//                pieceLabels.remove(key);
//                JLabel label = pieceLabels.get(key);
//                if (label != null) {
//                    remove(label);
//                }
//            }
//        }
//        invalidate();
//        revalidate();
//        repaint();
//    }
public void deleteChessPiece(ChessPiece piece) {
    if (piece != null) {
        String key = getKeyFromValue(pieceBox, piece);
        if (key != null) {
            System.out.println(key);
            pieceBox.remove(key);
            pieceLabels.remove(key);
            JLabel label = pieceLabels.get(key);
            if (label != null) {
                remove(label);
            }
        }
    }
    invalidate();
    revalidate();
    repaint();
}


    protected Point getBoardOffset() {
        int width = getWidth();
        int height = getHeight();
        Point p = new Point();
        p.x = (width - (cellSize * 8)) / 2;
        p.y = (height - (cellSize * 8)) / 2;

        return p;
    }
    public ChessPiece getPieceAt(Point coordinates){
        ChessPiece myPiece = null;

        for (ChessPiece piece : pieceBox.values()){
            if (piece.getCoordinates().x == coordinates.x && coordinates.y == piece.getCoordinates().y){
                myPiece = piece;
            }
        }
        return myPiece;
    }


    public void setHightlightCell(Point p) {
        if (highlightCell != p) {
            highlightCell = p;
            repaint();
        }
    }

}
public class MouseHandler extends MouseAdapter {

    private Component dragComponent;
    public static Component d;
    private final Board board;
    private final PieceMoves pieceMoves;
    private Point dragOffset;
    public static final boolean SNAP_TO_GRID = false;
    private Point dragOffsetToPoint;

    public MouseHandler(Board board, PieceMoves pieceMoves) {
        this.board = board;
        this.pieceMoves = pieceMoves;
    }

    public Board getBoard() {
        return board;
    }

    @Override
    public void mousePressed(MouseEvent e) {
        Component comp = getBoard().getComponentAt(e.getPoint());

        if (comp != null) {
            dragComponent = comp;
            dragOffset = new Point();
            dragOffset.x = e.getPoint().x - comp.getX();
            dragOffset.y = e.getPoint().y - comp.getY();

            dragOffsetToPoint = getBoard().pointToGrid(comp.getLocation());
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        if (dragComponent != null) {
            getBoard().setEnabled(true);
            Board board = getBoard();
            Point p = board.pointToGrid(e.getPoint());
            ChessPiece piece = board.getPieceAt(dragOffsetToPoint);

            if (p != null && pieceMoves.isAllowed(piece, p, dragOffsetToPoint)){
                ChessPiece piece1= board.getPieceAt(p);
                d = getBoard().getComponentAt(p);
                if (d != null) {
                    board.deleteChessPiece(piece1);
                }

                piece.getCoordinates().setLocation(p);
                board.setPieceGrid(dragComponent, p);
            } else {
                board.setPieceGrid(dragComponent, dragOffsetToPoint);
                piece.getCoordinates().setLocation(dragOffsetToPoint);
            }

            dragComponent = null;
            board.setHightlightCell(null);
        }
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        if (dragComponent != null) {
            Board board = getBoard();
            Point grid = board.pointToGrid(e.getPoint());
            if (SNAP_TO_GRID) {
                Point p = board.gridToPoint(grid);
                dragComponent.setLocation(p);
            } else {
                Point dragPoint = new Point();
                dragPoint.x = e.getPoint().x - dragOffset.x;
                dragPoint.y = e.getPoint().y - dragOffset.y;

                dragComponent.setLocation(dragPoint);
            }
            board.setHightlightCell(grid);
        }
    }
}
public class PieceMoves {
    private final Board board;

    public PieceMoves(Board board) {
        this.board = board;
    }

    private boolean isPathClear(Point coord, Point initial) {
        int deltaX = coord.x - initial.x;
        int deltaY = coord.y - initial.y;

        for (int i = 1; i < Math.max(Math.abs(deltaX), Math.abs(deltaY)); i++) {
            int x = initial.x + i * Integer.compare(deltaX, 0);
            int y = initial.y + i * Integer.compare(deltaY, 0);

            if (board.getPieceAt(new Point(x, y)) != null) {
                return false;
            }
        }
        return true;
    }

    private boolean isDiagonalClear(Point coord, Point initial) {
        int deltaX = coord.x - initial.x;
        int deltaY = coord.y - initial.y;

        int dirX = Integer.compare(deltaX, 0);
        int dirY = Integer.compare(deltaY, 0);

        for (int i = 1; i < Math.max(Math.abs(deltaX), Math.abs(deltaY)); i++) {
            int x = initial.x + dirX * i;
            int y = initial.y + dirY * i;

            if (board.getPieceAt(new Point(x, y)) != null) {
                return false;
            }
        }
        return true;
    }


    private boolean isValidPawnMove(Point coord, Point initial) {
        ChessPiece piece = board.getPieceAt(coord);
        ChessPiece initialPiece = board.getPieceAt(initial);

        var validation = false;
        int deltaX = initial.x - coord.x;
        int deltaY = initial.y - coord.y;

        if (piece == null) {

            if (initialPiece.getPlayer() == ChessPiece.Player.White){
                if ((deltaY == 1 || deltaY == 2) && coord.x == initial.x) {
                    validation = true;
                }
            } else if (initialPiece.getPlayer() == ChessPiece.Player.Black) {
                if ((deltaY == -1 || deltaY == -2) && coord.x == initial.x) {
                    validation = true;
                }
            }

        } else if (piece.getPlayer() != initialPiece.getPlayer()) {
            if (initialPiece.getPlayer() == ChessPiece.Player.White) {
                if (deltaY == 1 && deltaX == 1 || deltaY == 1 && deltaX == -1) {
                    validation = true;
                }
            }else if (initialPiece.getPlayer() == ChessPiece.Player.Black) {
                if (deltaY == -1 && deltaX == -1 || deltaY == -1 && deltaX == 1) {
                    validation = true;
                }
            }
        }
        return validation;
    }


    private boolean isValidKnightMove(Point coord, Point initial) {
        ChessPiece piece = board.getPieceAt(coord);
        ChessPiece initialPiece = board.getPieceAt(initial);
        var validation = false;

        if (piece == null || piece.getPlayer() != initialPiece.getPlayer()){
            var deltaX = initial.x - coord.x;
            var deltaY = initial.y - coord.y;

            if (Math.abs(deltaX) == 2 && Math.abs(deltaY) == 1){
                validation = true;
            }else validation = Math.abs(deltaX) == 1 && Math.abs(deltaY) == 2;
        }
        return validation;
    }

    private boolean isValidRookMove(Point coord, Point initial) {
        ChessPiece piece = board.getPieceAt(coord);
        ChessPiece initialPiece = board.getPieceAt(initial);
        boolean validation = false;

        if (piece == null || piece.getPlayer() != initialPiece.getPlayer()) {
            if (coord.x == initial.x || coord.y == initial.y) {
                if (isPathClear(initial, coord)) {
                    validation = true;
                }
            }
        }
        return validation;
    }


    private boolean isValidBishopMove(Point coord, Point initial) {
        ChessPiece piece = board.getPieceAt(coord);
        ChessPiece initialPiece = board.getPieceAt(initial);
        boolean validation = false;

        if (piece == null || piece.getPlayer() != initialPiece.getPlayer()) {
            if (Math.abs(coord.x - initial.x) == Math.abs(coord.y - initial.y)) {
                if (isDiagonalClear(initial, coord)) {
                    validation = true;
                }
            }
        }
        return validation;
    }


    private boolean isValidQueenMove(Point coord, Point initial) {
        return isValidBishopMove(coord , initial) || isValidRookMove(coord , initial);
    }

    private boolean isValidKingMove(Point coord, Point initial) {
        ChessPiece piece = board.getPieceAt(coord);
        ChessPiece initialPiece = board.getPieceAt(initial);
        var validation = false;

        if (piece == null || piece.getPlayer() != initialPiece.getPlayer()){
            var deltaX = Math.abs(initial.x - coord.x);
            var deltaY = Math.abs(initial.y - coord.y);

            if (deltaX == 1 && deltaY == 0){
                validation = true;
            }else if (deltaX == 0 && deltaY == 1) validation = true;
            else if (deltaX == 1 && deltaY == 1) validation = true;
        }
        return validation;
    }


    public boolean isAllowed(ChessPiece piece,Point coord, Point initial) {

        System.out.println(piece.getCoordinates());

        return switch (piece.getRank()) {
            case Pawn -> isValidPawnMove(coord, initial);
            case Knight -> isValidKnightMove(coord,initial);
            case Bishop -> isValidBishopMove(coord , initial);
            case Rook -> isValidRookMove(coord, initial);
            case Queen -> isValidQueenMove(coord, initial);
            case King -> isValidKingMove(coord, initial);
        };
    }
}

我尝试使用remove方法从JPanel中删除与已删除棋子相关的JLabel,但该棋子的视觉表示仍然保留在屏幕上。我预计通过删除 JLabel,棋子的视觉表示也会从屏幕上删除。

java swing
1个回答
0
投票

对于国际象棋游戏,您通常根本不会使用 Swing 组件,而是进行自定义绘画。它可以更好地控制您需要的元素的位置。请参阅 https://docs.oracle.com/javase/tutorial/uiswing/painting/

到达那里后,删除元素仅意味着将其从模型中删除并重新渲染模型,这将绘制除删除的元素之外的所有内容。

© www.soinside.com 2019 - 2024. All rights reserved.