Swing:组件不会消失,直到我将鼠标悬停在组件上

3

我正在开发一个小型游戏,作为学校的一个小项目,它是基于Java Swing实现的。我已经完成了所有的逻辑和GUI界面。

这个游戏(蛇与梯子)有36个正方形(JButtons),每个正方形都有可以用于放置玩家棋子的JPanels。换句话说,我有36个按钮,它们都有JPanels,在这些JPanels内部可以放置按钮。在每个正方形上,我都放置了一个Action Listener来检查是谁的回合,如果玩家可以移动到这里,并且当满足这些条件(当然还有更多其他条件)时,将玩家的按钮移动到该正方形上。

现在出现了一些错误。当玩家移动棋子时,它会同时出现在新的正方形和旧的正方形上。只有当我将鼠标悬停在旧位置上时,棋子才消失。

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

//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解释

1
在更改组件内容后,您似乎没有调用revalidate()repaint()来刷新您的容器(JPanels)。我建议您在ActionListeners结束时执行此操作。第一个方法告诉布局管理器重新布置组件,第二个方法清除可能剩余的任何脏像素。 - DontKnowMuchBut Getting Better
1
如果这不能解决问题,那么请考虑在您的问题中发布一个有效的 [mre]。 - DontKnowMuchBut Getting Better
1个回答

2
当更改容器内的组件时,如果容器正确使用布局管理器,您应该始终在容器或其父容器之一上调用revalidate(),因为这将告诉布局管理器和任何嵌套容器的管理器重新布置它们的组件。当从容器中删除组件时,通常还需要在容器上调用repaint()以请求对其及其子级的重绘,主要是为了清除任何可能残留的脏像素。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接