2016-11-06 1 views
-1

저는 대학 프로젝트로 게임을 쓰고 있습니다. JCanvas를 사용하여 게임을 표시하고 그 부분은 완벽하게 작동하지만 '게임', '게임', '종료'등의 옵션을 선택할 수있는 메뉴를 추가하고 싶습니다.JPanel에서 Canvas 게임을 시작하는 방법은 무엇입니까?

JCanvas 및 JPanel (후자는 메뉴 임). 하지만 패널에서 게임을 시작하면 프레임이 정지됩니다.
몇 가지 테스트를 실행했는데 문제는 JPanels actionListener에서 playGame() 메서드를 호출 할 때 캔버스가 해당 메서드가 반환 될 때까지 업데이트 할 수 없다는 것입니다. https://github.com/nodar86/prog3-snake

답변

2

모두 다시 그리기 및 이벤트 파견 (The Event Dispatch Thread 수행한다 : 즉 더 도움이된다면

public class Main { 

public static Game game = new Game(); 
private static JFrame mainFrame = new JFrame("Snake"); 
private static MenuPanel menuPanel = new MenuPanel(); 

public static void main(String[] args) { 
    mainFrame.setLayout(new BorderLayout()); 

    mainFrame.add(menuPanel, BorderLayout.SOUTH); 
    mainFrame.pack(); 
    mainFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
    mainFrame.setVisible(true); 

} 

static void playGame(){ 
    mainFrame.setVisible(false); 
    mainFrame.remove(menuPanel); 
    menuPanel.setEnabled(false); 

    ScoreboardPanel scoreboardPanel = new ScoreboardPanel(); 
    mainFrame.add(scoreboardPanel, BorderLayout.NORTH); 

    game.addPanel(scoreboardPanel); 
    mainFrame.add(game, BorderLayout.CENTER); 
    mainFrame.pack(); 
    mainFrame.setVisible(true); 

    // ANYTHING here stops the frame's rendering until playGame() returns (like game.play() or sleep(x) 
} 

}

public class MenuPanel extends JPanel { 

private class MenuActionListener implements ActionListener { 
    public void actionPerformed(ActionEvent actionEvent){ 
     switch (actionEvent.getActionCommand()){ 
      case "play": 
       // TODO This somehow breaks everything. The game loop runs but the window freezes. 
       Main.playGame(); 
       break; 
      case "highscore": 
       break; 
      case "leveleditor": 
       break; 
      case "exit": 
       System.exit(0); 
       break; 
     } 
    } 
} 

그리고 여기에 전체 코드입니다 : 여기

는 관련 부분입니다 EDT). Game.play 메서드는 이벤트 리스너에서 호출되어 sleep을 사용하여 EDT를 차단하므로 Swing에서 프레임을 다시 칠할 기회가 없습니다.

가장 손쉬운 방법은 Game.play의 수제 타이머를 javax.swing.Timer으로 대체하는 것입니다. 타이머의 각 진드기에서 게임의 진드기를 에뮬레이트해야합니다. 이렇게하면 Swing이 필요에 따라 다시 칠할 수 있습니다. 미리 타이머를 준비하면 메뉴 청취자가 타이머를 시작하고 중지 할 수 있습니다.

사이드 노트 : 아마도 special menu components 메뉴를 사용하는 것이 좋습니다.

+0

감사합니다. EDT에 대한 정보를 링크하고 설명해 주셔서 감사합니다. 이것은 모든 것들이 스윙에 도움이 될 것입니다! –

2

당신이 "캔버스"를 사용하지 않는 한 "JCanvas"와 같은 것이 없습니다. (in here your Game class extends Canvas.) 가볍고 중량이 많은 툴킷을 더 이상 섞어서 사용하지 않기를 권장합니다. 동일한 GUI. 하지만 거의 완료된 것 같아서 kgeorgiy의 대답을 시도해보십시오.

관련 문제