2015-06-02 50 views
0

運行我的Java遊戲時出現一些奇怪的錯誤。作爲計算機科學課的一個項目,我一直在爲這個遊戲工作幾個星期,它將於2015年6月4日到期,所以我很感激任何幫助。最初,我在一個名爲Game的類中編寫了遊戲,並從一個名爲run的靜態方法中運行它。後來,我決定在名爲Control的類中添加一個GUI菜單。現在運行遊戲,我調用Control類中的主要方法。這個菜單有一個帶有動作監聽器的按鈕。當按鈕被點擊時,Game類中的run方法被調用。如果我點擊並直接運行run方法,遊戲就可以正常工作。但是,如果我點擊調用運行方法的按鈕,它將繪製一個框架,但不是實際的遊戲。運行Java遊戲時出現線程錯誤

這裏是我的GUI代碼:

public class Control extends JFrame implements ActionListener { 

    // JPanel 
    public JPanel pnlButton = new JPanel(); 

    // Buttons 
    public JButton btnAddFlight = new JButton("Multiplayer"); 
    public JButton single = new JButton("Singleplayer"); 

    public Control() throws IOException,InterruptedException { 
     super("Bouncy Ball"); 
     //Set button size 
     btnAddFlight.setBounds(150, 400, 220, 30); 
     single.setBounds(150,350,220,30); 

     // JPanel bounds 
     pnlButton.setBounds(0, 0, 500, 500); 
     pnlButton.setBackground(Color.WHITE); 

     // Adding the Bouncy Ball logo to JPanel 
     String path = "gg.jpg"; 
     File file = new File(path); 
     BufferedImage image = ImageIO.read(file); 
     JLabel label = new JLabel(new ImageIcon(image)); 
     label.setBounds(179,50,150,150); 

     //Action Listener setup 
     single.addActionListener(this); 

     //add buttons and title logo to JPanel 
     pnlButton.add(btnAddFlight); 
     pnlButton.add(label); 
     pnlButton.add(single); 

     //Set up and add the instructions to the JPanel 
     JLabel gg = new JLabel("Welcome to Bouncy Ball, a game where you have to manipulate"); 
     gg.setFont(new Font("Serif", Font.PLAIN, 18)); 
     gg.setBounds(0,10,500,500); 
     pnlButton.add(gg); 
     JLabel f = new JLabel("the window size with WASD to win! Click the buttons to start."); 
     f.setFont(new Font("Serif", Font.PLAIN, 18)); 
     f.setBounds(0,28,500,500); 
     pnlButton.add(f); 
     pnlButton.setLayout(null); 

     //Add JPanel to JFrame 
     this.add(pnlButton); 

     // JFrame properties 
     setSize(500, 500);  
     setTitle("Bouncy Ball"); 
     setLocationRelativeTo(null); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setVisible(true);; 
    } 

    @Override 
    public void actionPerformed(ActionEvent submitClicked) { 
     try{ 
      isClicked = true; 

      Game.run(); 
     } 
     catch(InterruptedException a){} 
    } 

    public static void main(String[] args) throws IOException,InterruptedException{ 
     new Control(); 
    } 
} 

,這裏是我的遊戲類的run方法:

public static void run() throws InterruptedException { 
    //Setting up JFrame 
    frame = new KeyFrame("Bouncy Ball"); 
    frame.setSize(1000, 1000); 

    //Setting up Scanner and get user level input 
    Scanner scan = new Scanner (System.in); 
    System.out.println("Level one, two, three, or four?(must be an int, four is multiplayer)"); 
    f = scan.nextInt(); 

    //Display JFrame 
    frame.setVisible(true); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.toFront(); 

    //Add Game JPanel 
    game = new Game(); 
    frame.add(game); 

    //Setting up game basics 
    b = new Ball(game,0,0,30,30); 
    setUpLevel(); 
    objList.add(0,b); 

    //Main Game Loop 
    while (true) { 
     //Request Focus 
     game.requestFocusInWindow(); 

     //Update current Time 
     lastStartTime = System.currentTimeMillis(); 

     //Move the ball and the player 
     p.move(); 
     b.move(); 

     //Refresh JPanel 
     game.repaint(); 
     Thread.sleep(10); 

     //Check if the player wins or loses 
     checkWin(); 
     checkLoss(); 
    } 
} 

如果我直接調用run方法它的工作原理,但如果我點擊GUI中的按鈕。我感覺這是一個線程問題,因爲一旦運行被調用,主線程就結束了。儘管如此,我並不是百分之百確定的。我很感激任何迴應,我一直在爲這個遊戲工作幾個星期,作爲我的計算機科學課程的一個項目,它將於2015年6月4日到期。

回答

1

Swing是單線程的 - 所有的繪畫,事件等...發生在這個線程(命名爲EDT)。在EDT上調用Game.run方法,該方法又執行長時間運行的任務(例如while (true)Thread.sleep) - 這可以防止EDT執行其他任何操作。要執行動畫,請考慮使用Thread,或更好的是Swing Timer

+4

搖擺定時器是簡單的,但如果你要告訴他們創建一個線程,那麼你也應該說,該線程不能調用()''比其他SwingUtilities.invokeLater任何Swing方法。 –

+0

@copeg非常感謝。我創建了一個新線程,並從那裏調用了我的run方法,現在一切正常。 – user1615326

+0

@ user1615326,如果使用線程,請注意上述RE @詹姆斯大型註釋:調用搖擺(如'repaint','requestFocusInWindow')應該使用'SwingUtilities.invokeLater'派往EDT。 – copeg