我正在尝试绘制一个在游戏循环中扩展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保持可见,从而导致这种情况。但是,我可能错了。即使这是问题,我也无法想到任何解决方案。也许我应该将按钮监听器移动到另一个类?提前谢谢!
答案 0 :(得分:2)
您正在阻止事件调度线程,这会阻止UI更新。除其他事项外,EDT负责处理重绘请求。你的游戏循环是在EDT的背景下运行的......
actionPerformed
在EDT内执行,调用setGamePanelVisible
,调用调用GameManager
的{{1}},阻止... {/ p>
请查看Concurrency in Swing了解详情。
Swing不是线程安全的,所以你不能简单地启动一个新的run
并希望能解决所有问题,你需要确保对UI的所有更新(包括对信息的更新) UI可能需要)并在EDT的上下文中制作
其中一个更简单的解决方案是使用Swing Thread
,这将允许您安排在EDT上下文中执行的定时更新。有关详细信息,请参阅How to use Swing Timers