Сетка jpanels (для подключения четыре игры) - paintComponent работает только для верхней левой панели - PullRequest
0 голосов
/ 28 ноября 2018

Я пытаюсь сделать простое подключение четырех GUI, используя сетку JPanels, каждая из которых рисует цветной диск, когда кнопка под ними нажата, а панели под ней заполнены.Перед добавлением правил игры я пытаюсь убедиться, что кнопки и дисплей работают правильно.Но это не работает - только верхняя левая панель отображает диск (после нажатия кнопки 1 6 раз).вот мой код:

public class ConnectFourFrame extends JFrame {

private final JPanel gamePanelsPanel; // panel to hold the game panels
private final GamePanel[][] gamePanels; // a 2D array to hold the grid of panels to display the game disks
private final JPanel buttonsPanel; // panel to hold the buttons panels
private final JPanel gameButtonsPanel; // panel to hold the game buttons to add disk to a column
private final JButton[] gameButtons; // an array to hold the game buttons
private final JPanel clearButtonPanel; // panel to hold the clear button
private final JButton clearButton; // button to clear the game grid from disks

private enum Turn {RED_PLAYER, BLUE_PLAYER}; // keeps track of which players turn it is 
private Turn turn;


// no argument constructor
public ConnectFourFrame() {

    super("Connect Four");
    this.setLayout(new BorderLayout());

    //add panels to hold the game panel and the buttons
    gamePanelsPanel = new JPanel();
    add(gamePanelsPanel, BorderLayout.CENTER);  
    buttonsPanel = new JPanel();
    buttonsPanel.setLayout(new BorderLayout());
    add(buttonsPanel, BorderLayout.SOUTH);

    //set up game panels
    gamePanelsPanel.setLayout(new GridLayout(6,7,3,3));
    gamePanelsPanel.setBackground(Color.BLACK);
    gamePanels = new GamePanel[6][7];
    for (int i = 0; i < 6; i++) {
        for (int j = 0; j < 7; j++) {
            gamePanels[i][j] = new GamePanel(false, Color.WHITE);
            gamePanelsPanel.add(gamePanels[i][j]);
        }
    }


    //set up game and clear buttons
    gameButtonsPanel = new JPanel();
    gameButtonsPanel.setLayout(new GridLayout(1,7));
    clearButtonPanel = new JPanel();

    gameButtons = new JButton[7];
    for (int i = 0; i < 7; i++) {
        gameButtons[i] = new JButton("" + (i+1));
        gameButtonsPanel.add(gameButtons[i]);
    }

    clearButton = new JButton("CLEAR");
    clearButtonPanel.add(clearButton);

    buttonsPanel.add(gameButtonsPanel, BorderLayout.NORTH);
    buttonsPanel.add(clearButtonPanel, BorderLayout.SOUTH);
    add(buttonsPanel, BorderLayout.SOUTH);

    // register event handlers
    ClearButtonHandler clearButtonHandler = new ClearButtonHandler();
    clearButton.addActionListener(clearButtonHandler);
    GameButtonHandler gameButtonHandler = new GameButtonHandler();
    for (int i = 0; i < 7; i++) {
        gameButtons[i].addActionListener(gameButtonHandler);
    }

    turn = Turn.RED_PLAYER; //set first turn to player1

}

// inner class for game button event handling
private class GameButtonHandler implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        // get the number of the pressed button
        int pressedButtonNum = Integer.parseInt(((JButton) e.getSource()).getActionCommand());
        // display disk in top empty panel of the column 
        for (int i = 5; i >= 0; i--) {
            if (!gamePanels[i][pressedButtonNum - 1].isFull()) {
                if (turn == Turn.RED_PLAYER) {
                    gamePanels[i][pressedButtonNum - 1].setDiskColor(Color.RED);
                    turn = Turn.BLUE_PLAYER;
                }
                else {
                    gamePanels[i][pressedButtonNum - 1].setDiskColor(Color.BLUE);
                    turn = Turn.RED_PLAYER;
                }
                gamePanels[i][pressedButtonNum - 1].setFull(true);
                gamePanels[i][pressedButtonNum - 1].repaint();
                return;
            }
        }
            // if column is full display message to try again
            JOptionPane.showMessageDialog(gamePanelsPanel, "Column " + pressedButtonNum + " is full. Try again.");
    }

}

public class GamePanel extends JPanel{

private boolean isFull; // true if the panel has a disk in it. default is empty (false).
private Color diskColor; //color of disks. default is white (same as background)


public GamePanel(boolean isFull, Color diskColor) {
    super();
    this.isFull = isFull;
    this.diskColor = diskColor;
}

public Color getDiskColor() {
    return diskColor;
}

public void setDiskColor(Color diskColor) {
    this.diskColor = diskColor;
}

public boolean isFull() {
    return isFull;
}

public void setFull(boolean isFull) {
    this.isFull = isFull;
}


@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    this.setBackground(Color.WHITE);

    g.setColor(diskColor);
    g.fillOval(this.getX() + this.getWidth()/4 , this.getY() + this.getHeight()/4, this.getWidth()/2, this.getHeight()/2);
}

}

1 Ответ

0 голосов
/ 28 ноября 2018

Проблема прямо здесь ...

g.fillOval(this.getX() + this.getWidth()/4 , this.getY() + this.getHeight()/4, this.getWidth()/2, this.getHeight()/2);

Контекст Graphics, переданный вашему методу paintComponent, уже переведен позицией компонентов x / y, что означает, чтоверхний / левый угол компонента всегда 0x0

g.fillOval(this.getWidth()/4 , this.getHeight()/4, this.getWidth()/2, this.getHeight()/2);

, вероятно, будет работать лучше

Кроме того, вызов this.setBackground(Color.WHITE); внутри paintComponent нежелателен, так как он настроитСитуация, когда по новому циклу рисования будет запланировано, снова и снова.Не изменяйте состояние пользовательского интерфейса из метода рисования

...