英文:
Swing: Component wont dissapear until I hover over the component
问题
我正在开发一个小型的游戏,使用Java Swing作为学校的小项目。我已经完成了所有的逻辑和GUI。
这个游戏(蛇和梯子)有36个方格(JButtons),每个方格里面都有JPanel,可以用来放置玩家的棋子(JButtons)。换句话说,我有36个按钮,它们都有JPanel,而所有的JPanel都可以放置按钮。在每个方格上,我都放置了一个动作监听器,用来检查轮到谁了,玩家是否可以在这里移动,只有在这些条件(当然还有更多条件)满足的情况下,玩家的按钮才会被移动到该方格。
现在来说一下有问题的部分。当玩家的棋子移动时,它会出现在新的方格上,并且还会出现在旧的方格上。只有当我将鼠标悬停在旧方格上时,棋子才会从旧方格上消失。
以下是可能有助于理解的一些代码:
// 这部分发生在另一个函数中。我只展示这部分,因为我认为这可能是函数中唯一相关的部分
spots[i][j].addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setGameSpotsAction(f,p,spotNr);
}
});
// 当点击一个方格/格子时要执行的操作
public void setGameSpotsAction(JFrame f, JPanel p, int nr) {
// ... (函数的其余部分)
} else if (latestRoll >= 2 && nr <= X*Y && playerPosition[playerTurn] + latestRoll == nr) {
// ... (函数的其余部分)
// 以下是关于移动玩家按钮的部分
playerPosition[playerTurn] += latestRoll;
movePlayerButton(nr);
spotPanels[spotNr].setVisible(true);
}
}
public void movePlayerButton(int spotNr){
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx=0;gbc.gridy=playerTurn-1;
spotPanels[spotNr].add(playerButtons[playerTurn],gbc);
spotPanels[spotNr].setVisible(true);
}
我尝试过的:
- 我尝试在每次棋子移动后调用 "frame.pack()"。似乎第一次调用时有效,但之后窗口开始表现奇怪。(至少我尝试了一些方法...)
- 我尝试过使用 EventQueue.InvokeLater 和 EventQueue.invokeAndWait。这很可能不起作用,因为我不太清楚如何正确使用它。参考链接:https://stackoverflow.com/questions/22534356/java-awt-eventqueue-invokelater-explained
英文:
I am developing a small game in java swing as a small school project. I am done with all the logic and GUI.
The game(Snakes and Stairs) has 36 squares(JButtons) and each of those have Jpanels inside that can be used to put the players piece at(JButtons). In other words, I have 36 buttons which all have Jpanels inside them, and all the JPanels can reside buttons. On each square I have put an action listener that checks whose turn it is, if the player can move here, and moves the players button to that square only if those conditions(and more ofcourse) are true.
Now comes the buggy part. When a players piece moves, it appears on the new square and the old one. The piece only dissapears from the old square if I hover over it.
Some code that might help understand:
//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
}
What I have tried:
- I have tried to call "frame.pack()" after each time a piece moves. It seemed to work the first time it is called, but after that the frame begins to act wierd.(I at least tried something...)
- I have tried EventQueue.InvokeLater and EventQueue.invokeAndWait. This most likely didn't work because I don't really know how to use it properly. https://stackoverflow.com/questions/22534356/java-awt-eventqueue-invokelater-explained
答案1
得分: 2
更改容器内的组件时,如果容器适当使用了布局管理器,您总应在容器或其父容器之一上调用 revalidate()
,因为这会通知布局管理器和任何嵌套容器的管理器重新布局其组件。通常还应调用容器的 repaint()
方法,以请求对其本身及其子组件进行重绘,主要是为了清除任何可能残留的脏像素。当从容器中移除组件时,后者尤为重要。
英文:
When changing components held within a container, one that properly uses a layout manager, you always should call revalidate()
on the container or one of its parent containers, since this will tell the layout manager and the managers of any nested containers to re-layout their components. You also often will want to call repaint()
on the container to request a repainting of it and its children, mainly to clear any potentially left-over dirty pixels. This latter is especially true when removing components from the container.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论