可以在游戏循环中绘制到JPanel

时间:2014-12-21 21:13:44

标签: java swing jpanel

我正在尝试绘制一个在游戏循环中扩展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保持可见,从而导致这种情况。但是,我可能错了。即使这是问题,我也无法想到任何解决方案。也许我应该将按钮监听器移动到另一个类?提前谢谢!

1 个答案:

答案 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