我试图在游戏循环期间扩展 JPanel 的 MapPanel 上进行绘制,但失败了。但是,如果我在循环之外执行此操作,它会成功绘制。这是我的相关代码:
MenuPanel.java:
public void actionPerformed(ActionEvent e) {
JButton pushedButton =(JButton) e.getSource();
if(pushedButton == play)
guiManager.setGamePanelVisible(true);
else if(pushedButton == settings)
guiManager.setSettingsPanelVisible();
else if(pushedButton == credits)
guiManager.setCreditsPanelVisible();
else if(pushedButton == highScores)
guiManager.setHighScoresPanelVisible();
else if(pushedButton == help)
guiManager.setHelpPanelVisible();
}
GUIManager.java:
...
public void setGamePanelVisible(boolean gameStarted){
GamePanel gp = new GamePanel(this);
setContentPane(gp);
gp.initiate();
}
...
GamePanel.java
public void initiate(){
this.gm = new GameManager(this); // constructs the game manager and triggers the game loop
}
GameManager.java
public GameManager(GamePanel gp) {
this.gp = gp;
this.run();
}
private void run(){
while(running){
draw();
try{
sleep(1000);
} catch (InterruptedException e) {
System.out.println("Interrupted at GameManager.java");
}
}
我的预测是,游戏循环在 MenuPanel 仍然可见时开始(在 setGamePanelVisible 方法中),并且由于它永远不会退出该方法,MenuPanel 保持可见,从而导致这种情况。然而,我可能是错的。即使这是问题,我也想不出任何解决办法。也许我应该将按钮监听器移到另一个类?预先感谢您!
最佳答案
您正在阻止事件调度线程,这会阻止 UI 更新。 EDT 负责处理重绘请求等。您的游戏循环正在 EDT 的上下文中运行...
actionPerformed
在 EDT 中执行,它调用 setGamePanelVisible
,后者调用 GameManager
,后者调用 run
,其中 block ...
看看Concurrency in Swing了解更多详情。
Swing 不是线程安全的,因此您不能简单地启动一个新的 Thread
并希望这能解决所有问题,您需要确保对 UI 的所有更新(包括对以下信息的更新) UI 可能需要)并在 EDT 上下文中制作
更简单的解决方案之一是仅使用 Swing Timer
,它允许您安排在 EDT 上下文中执行的定期、定时更新。请参阅How to use Swing Timers了解更多详情
关于java - 游戏循环期间无法绘制到 JPanel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27593900/