3

我正在用 java swing 开发一个小游戏作为一个小型学校项目。我完成了所有的逻辑和 GUI。

游戏(Snakes and Stairs)有 36 个方块(JButtons),每个方块内部都有 Jpanels,可用于将玩家放在(JButtons)上。换句话说,我有 36 个按钮,里面都有 Jpanels,所有的 JPanel 都可以驻留按钮。在每个方格上,我都放置了一个动作监听器,它检查轮到谁了,如果玩家可以移动到这里,并且只有当这些条件(当然还有更多)为真时才将玩家按钮移动到该方格。

现在是错误的部分。当玩家棋子移动时,它会出现在新方格旧方格上。如果我将鼠标悬停在它上面,它只会从旧广场上消失。

一些可能有助于理解的代码:

//this happens in another function. I only show this, because i think this is the only part relevant from the function
spots[i][j].addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        //EventQueue.invokeLater(()->setGameSpotsAction(f,p,spotNr));
                        setGameSpotsAction(f,p,spotNr);
                    }
                });


//action to do when a spot/square is pressed
    public void setGameSpotsAction(JFrame f, JPanel p, int nr) {//nr is the spot where the piece should go
        if(nr == X*Y && playerPosition[playerTurn] + latestRoll == nr){//if dice is rolled
            f.remove(p);
            winnerwinnerchickendinner.setText(namesArr[playerTurn]+" WON!!!!!!");
            JPanel panel = new JPanel(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx=0;gbc.gridy=0;panel.add(winnerwinnerchickendinner,gbc);
            f.getContentPane().add(panel);
        } else if (latestRoll >= 2 && nr <= X*Y && playerPosition[playerTurn] + latestRoll == nr) {//
                int sot = snakeOrStairs[playerPosition[playerTurn] + latestRoll];//sot stands for Snake Or sTair
                //if just regular square/spot
                if(playerPosition[1] != playerPosition[2]){//if player moves and the previous spot is empty, make panel invisible.
                    spotPanels[playerPosition[playerTurn]].setVisible(false);
                }
                if (sot == 0) {
                    playerPosition[playerTurn] += latestRoll;//button has new position
                    movePlayerButton(nr);
                    //EventQueue.invokeLater(()->{movePlayerButton(nr);});
                } else if (sot > 0) {//if positive number, we can go up!!
                    playerPosition[playerTurn] += latestRoll + sot;//button has new position
                    movePlayerButton(nr + sot);
                    //EventQueue.invokeLater(()->{movePlayerButton(nr);});
                } else {//god damn it we going down
                    playerPosition[playerTurn] += latestRoll - sot;//button has new position
                    movePlayerButton(nr - sot);
                    //EventQueue.invokeLater(()->{movePlayerButton(nr);});
                }
            changePlayerTurn(diceLabelText[1], diceLabelText[2]);
            roll.setEnabled(true);//next player can now roll
        }

    }
public void movePlayerButton(int spotNr){
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx=0;gbc.gridy=playerTurn-1;
        spotPanels[spotNr].add(playerButtons[playerTurn],gbc);//move players button to the new spot
        spotPanels[spotNr].setVisible(true);//set the panel to visible
    }

我试过的:

  • 每次一块移动后,我都尝试调用“frame.pack()”。它似乎在第一次被调用时起作用,但在那之后框架开始变得奇怪。(我至少尝试了一些东西......)
  • 我已经尝试过 EventQueue.InvokeLater 和 EventQueue.invokeAndWait。这很可能不起作用,因为我真的不知道如何正确使用它。java.awt.EventQueue.invokeLater 解释
4

1 回答 1

2

当更改容器中保存的组件时,一个正确使用布局管理器的组件,您始终应该调用revalidate()容器或其父容器之一,因为这将告诉布局管理器和任何嵌套容器的管理器重新布局其组件. 您还经常需要调用repaint()容器来请求重新绘制它及其子项,主要是为了清除任何可能残留的脏像素。后者在从容器中移除组件时尤其如此。

于 2020-09-26T16:38:52.173 回答