Я пытаюсь использовать MapPanel, который расширяет JPanel во время игрового цикла, и он терпит неудачу. Однако, если я делаю это за пределами цикла, он успешно рисует. Вот мой код:
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 остается видимым, что приводит к этой ситуации. Однако я могу ошибаться. Даже если это проблема, я не мог думать о каком-либо решении. Может быть, я должен переместить прослушиватель кнопок в другой класс? Заранее спасибо!
Вы блокируете поток Dispatching Event, который предотвращает обновление пользовательского интерфейса. EDT отвечает за, среди прочего, обработку запросов на перерисовку. Ваш игровой цикл запущен из контекста EDT...
actionPerformed
выполняется в EDT, который вызывает setGamePanelVisible
, который вызывает GameManager
который вызывает run
, который блокирует...
Взгляните на параллелизм в Swing для получения более подробной информации.
Swing не является потокобезопасным, поэтому вы не можете просто развернуть новую Thread
и надеяться, что все это исправит, вам нужно убедиться, что все обновления в пользовательском интерфейсе (включая обновления информации, которые могут иметь пользовательский интерфейс) и сделаны из контекст EDT
Одним из простых решений является просто использовать Swing Timer
, который позволит вам планировать регулярные, синхронизированные обновления, которые выполняются в контексте EDT. Подробнее о том, как использовать таймеры Swing для получения более подробной информации