Не могу нарисовать в JPanel во время игрового цикла

1

Я пытаюсь использовать 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 остается видимым, что приводит к этой ситуации. Однако я могу ошибаться. Даже если это проблема, я не мог думать о каком-либо решении. Может быть, я должен переместить прослушиватель кнопок в другой класс? Заранее спасибо!

  • 0
    Где / что такое игровой цикл? Как это называется? Звучит так, будто вы блокируете поток диспетчера событий, но это только предположение. Рассмотрите пример, который демонстрирует вашу проблему. Это приведет к меньшему беспорядку и лучшим ответам
  • 0
    @MadProgrammer Удалил неактуальный код и добавил немного. Я думаю, это то, что я пытаюсь объяснить.
Показать ещё 2 комментария
Теги:
swing
jpanel

1 ответ

2
Лучший ответ

Вы блокируете поток Dispatching Event, который предотвращает обновление пользовательского интерфейса. EDT отвечает за, среди прочего, обработку запросов на перерисовку. Ваш игровой цикл запущен из контекста EDT...

actionPerformed выполняется в EDT, который вызывает setGamePanelVisible, который вызывает GameManager который вызывает run, который блокирует...

Взгляните на параллелизм в Swing для получения более подробной информации.

Swing не является потокобезопасным, поэтому вы не можете просто развернуть новую Thread и надеяться, что все это исправит, вам нужно убедиться, что все обновления в пользовательском интерфейсе (включая обновления информации, которые могут иметь пользовательский интерфейс) и сделаны из контекст EDT

Одним из простых решений является просто использовать Swing Timer, который позволит вам планировать регулярные, синхронизированные обновления, которые выполняются в контексте EDT. Подробнее о том, как использовать таймеры Swing для получения более подробной информации

Ещё вопросы

Сообщество Overcoder
Наверх
Меню