初始化后 JButtons 未显示 [Java Swing]

JButtons not showing up after initialisation [Java Swing]

我知道这里有很多关于堆栈溢出的问题,关于 JElements 没有出现,都是因为有人忘记在构造函数的末尾添加 setVisible(true)。但至少我相信我的问题有所不同。我目前正在为大学制作国际象棋游戏,为此我有

在我写更多之前又是一个愚蠢的错误,这里是代码:

import javax.swing.*;
import Pieces.*;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Game extends JFrame {
    private static final int width = 8;
    private static final int height = 8;

    private static Piece clicked;

    private static Piece[][] fields = new Piece[width][height];

    private JPanel main = new JPanel();

    public static void init(JPanel g) {
        for (int y = 0; y < fields.length; y++) {
            for (int x = 0;  x < fields[y].length; x++) {

                if (y == 1) fields[y][x] = new Pawn(x, y, true); //2nd or 7th row is filled with pawns
                else if (y == 6) fields[y][x] = new Pawn(x, y, false);
                else {
                    fields[y][x] = new Empty(x,y,true);
                }

                fields[y][x].addActionListener(e -> {
                    var p = (Piece) e.getSource();
                    System.out.println(p.getX() + p.getY());
                });

                g.add(fields[y][x]);
            }
        }
    }

    public Game() {
        main.setBackground(Color.blue.darker());
        main.setLayout(new GridLayout(8,8));
        this.setSize(800,800);

        init(main);
        this.add(main);

        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    public static void main(String[] args) {
        var g = new Game();
    }
}
package Pieces;

import javax.swing.*;

public abstract class Piece extends JButton {
    private int x;
    private int y;
    private final boolean isWhite;

    public Piece(int x, int y, boolean isWhite) {
        this.x = x;
        this.y = y;
        this.isWhite = isWhite;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public boolean isWhite() {
        return isWhite;
    }

    public boolean canMoveTo(int toX, int toY) {
        return true;
    }
}

每个 Piece 扩展 class 的设置完全像这样:

package Pieces;

import java.awt.*;

public class Pawn extends Piece{
    public Pawn(int x, int y, boolean isWhite) {
        super(x, y, isWhite);
        this.setText(isWhite ? "Pawn" : "pawn");
    }
}

预期行为:

实际行为:

您不能像这样覆盖 getXgetY,布局管理器使用这些属性来布局组件。

相反,可以使用 Point 来存储虚拟或“单元格”位置

public static abstract class Piece extends JButton {
    private final boolean isWhite;
    private Point cell;

    public Piece(int x, int y, boolean isWhite) {
        cell = new Point(x, y);
        this.isWhite = isWhite;
    }

    public Point getCell() {
        return cell;
    }

    public boolean isWhite() {
        return isWhite;
    }

    public boolean canMoveTo(int toX, int toY) {
        return true;
    }
}

可运行示例...

import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JFrame;
import java.awt.GridLayout;
import java.awt.Point;
import javax.swing.JButton;
import javax.swing.JPanel;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new BoardPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class BoardPane extends JPanel {
        private static final int width = 8;
        private static final int height = 8;

        private Piece clicked;

        private Piece[][] fields = new Piece[width][height];

        public BoardPane() {
            setBackground(Color.blue.darker());
            setLayout(new GridLayout(8, 8));
            buildBoard();
        }

        protected void buildBoard() {
            for (int y = 0; y < fields.length; y++) {
                for (int x = 0; x < fields[y].length; x++) {

                    if (y == 1) {
                        fields[y][x] = new Pawn(x, y, true); //2nd or 7th row is filled with pawns
                    } else if (y == 6) {
                        fields[y][x] = new Pawn(x, y, false);
                    } else {
                        fields[y][x] = new Empty(x,y,true);
                    }

                    fields[y][x].addActionListener(e -> {
                        var p = (Piece) e.getSource();
                        System.out.println(p.getCell());
                    });

                    add(fields[y][x]);
                }
            }
        }
    }

    public static abstract class Piece extends JButton {
        private final boolean isWhite;
        private Point cell;

        public Piece(int x, int y, boolean isWhite) {
            cell = new Point(x, y);
            this.isWhite = isWhite;
        }

        public Point getCell() {
            return cell;
        }

        public boolean isWhite() {
            return isWhite;
        }

        public boolean canMoveTo(int toX, int toY) {
            return true;
        }
    }

    public static class Pawn extends Piece {
        public Pawn(int x, int y, boolean isWhite) {
            super(x, y, isWhite);
            this.setText(isWhite ? "Pawn" : "pawn");
        }
    }

    public static class Empty extends Piece {
        public Empty(int x, int y, boolean isWhite) {
            super(x, y, isWhite);
            this.setText("X");
        }
    }
}