为什么paintComponents被调用但看不到?

时间:2019-01-01 02:02:06

标签: java swing grid-layout jcomponent

我有一个单元格的GridLayout,每个单元都扩展了JComponent。 GridLayout管理扩展JPanel的Board类,并将Board对象/面板与其他两个面板一起添加到主面板中。

这是单元格类别:

public class Cell extends JComponent{

    private int row;
    private int col;

    private int rowHeight;
    private int colWidth;

    private boolean active = false;

    private Color color;

    public Cell(int row, int col, Color color) {
        this.row = row;
        this.col = col;

        this.color = color;
    }

    public Cell(int row, int col, int rowHeight, int colWidth, Color color) {
        this.row = row;
        this.col = col;

        this.rowHeight = rowHeight;
        this.colWidth = colWidth;

        this.color = color;
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        paintSquare(g);
    }

    private void paintSquare(Graphics g) {
        g.setColor(color);
        g.fillRoundRect(
            (int) (col * colWidth),
            (int) (row * rowHeight),
            (int) (rowHeight),
            (int) (colWidth),
            10,
            10);

    }

    public int getCol()
    {
        return col;
    }

    public int getRow()
    {
        return row;
    }

    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }
}

这是董事会班级:

public class Board extends JPanel {

    public Cell[][] gameBoard;

    public final int GAME_ROWS;
    public final int GAME_COLUMNS;

    public int rowHeight;
    public int columnWidth;

    public Color selectedColor;

    public Board(int GAME_ROWS, int GAME_COLUMNS) {
        this.GAME_COLUMNS = GAME_COLUMNS;
        this.GAME_ROWS = GAME_ROWS;

        calculateDimensions();

        createGameBoard();

        setUpBoardPanel();
    }

    private void calculateDimensions() {
        rowHeight = (int) this.getHeight() / GAME_ROWS;
        columnWidth = (int) this.getWidth() / GAME_COLUMNS;
    }

    private void createGameBoard() {
        Random random = new Random();
        int cellColor;
        gameBoard = new Cell[GAME_ROWS][GAME_COLUMNS];
        for (int row = 0; row < GAME_ROWS; row++) {
            for (int col = 0; col < GAME_COLUMNS; col++) {
                cellColor = random.nextInt(Properties.COLORS.length);
                Cell newCell = new Cell(row, col, rowHeight, 
                    columnWidth,Properties.COLORS[cellColor]);
                gameBoard[row][col] = newCell;
            }
        }
    }

    private void setUpBoardPanel() {
        setLayout(new GridLayout(GAME_ROWS, GAME_COLUMNS));
        setPreferredSize(Properties.BOARD_TABLE_SIZE);
        setBorder(new EmptyBorder(20, 10, 0, 0));
        setBackground(Properties.BACKGROUND_COLOR);

        addBoardPanelComponents();
    }

    private void addBoardPanelComponents() {
        for(int r = 0; r < GAME_ROWS; r++) {
            for(int c = 0; c < GAME_COLUMNS; c++) {
                add(gameBoard[r][c]);
            }
        }
    }
}

主面板上的所有内容均显示完美,我可以看到添加了“面板”面板,因为当我更改其背景时,它会按设置显示。

我已经看了一堆教程,并称其为“超级正确”,所以我不确定如何正确添加和调用这些组件,而不会显示它们。

要查看完整的程序代码,可以转到我的github,但相关代码在上面。 TIA!

1 个答案:

答案 0 :(得分:2)

“核心”问题是,您不了解组件的坐标空间如何工作。

组件的x / y位置是相对于其父级的。任何组件/容器的左上角始终为0x0

所以当你做这样的事情...

g.fillRoundRect(
                (int) (col * colWidth),
                (int) (row * rowHeight),
                (int) (rowHeight),
                (int) (colWidth),
                10,
                10);

您要说的是,填充相对于组件本身左上角(始终为col * width的{​​{1}} x row * rowHeight的矩形

您应该做的更像是这样...

0x0

这将填充组件的整个可见区域。

但是为什么要使用g.fillRoundRect( 0, 0, getWidth() - 1, getHeight() - 1, 10, 10); getWidth。好吧,在这种情况下,这可以确保填充组件的整个可见区域,但是如何影响组件的大小?

首选方法是重写组件的getHeight方法并返回“首选”大小(所有条件都相同)。

getPreferredSize

这向父级布局管理器提供了有关组件“如何”布局的提示。

另一个问题是...

@Override
public Dimension getPreferredSize() {
    return new Dimension(colWidth, rowHeight);
}

这毫无意义,因为在组件经过布局遍历之前,其大小为 private void calculateDimensions() { rowHeight = (int) this.getHeight() / GAME_ROWS; columnWidth = (int) this.getWidth() / GAME_COLUMNS; } ,因此,基本上,您是说0x0rowHeight应该为{{1 }}:/

老实说,最好摆脱它。如果需要,将已知值直接播种到columnWidth

可运行的示例...

Blobs

0x0