2014-10-20 50 views
0

我建立一個Java虛擬寵物遊戲,目前該菜單面板做工精細,按鈕加載和運行,但是當我點擊我的新遊戲按鈕,這是應該推出到的GamePanel面板我得到一個nullpointerException。與Swing CardLayout問題

這是建立原始幀和的JPanel從切換的主類。

public class MainFrame extends JPanel { 

public JPanel mainPanel; 
public CardLayout cl; 
private final GamePanel gamePanel; 
private final MenuPanel menuPanel; 

/** 
* Constructs the main panel to be used to switch between panels. 
* 
*/ 
public MainFrame() { 

    // creates a new panel to add panels to. 
    cl = new CardLayout(); 

    // panel to be used as a main switch. 
    mainPanel = new JPanel(); 
    Dimension size = getPreferredSize(); 
    size.width = 600; 
    size.height = 600; 
    setPreferredSize(size); 
    setBackground(Color.BLACK); 

    add(mainPanel); 

    gamePanel = new GamePanel(); 
    menuPanel = new MenuPanel(); 

    // sets layout 
    mainPanel.setLayout(cl); 

    mainPanel.add(menuPanel, "menuPanel"); 
    mainPanel.add(gamePanel, "gamePanel"); 

} 

public void changePanel(String name) { 

    cl.show(mainPanel, name); 

} 

/** 
* Main frame used by the game. 
* 
* @param args 
*/ 
public static void main(String[] args) { 

MainFrame game = new MainFrame(); 

JFrame frame = new JFrame("Main Window"); 
frame.add(game); 
frame.pack(); 
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
frame.setVisible(true); 
frame.setResizable(false);  
frame.setLocationRelativeTo(null);    

} 

}

這是從我MenuPanel類應當被訪問changePanel()方法的代碼。

public class MenuPanel extends JPanel { 

MainFrame mf; 

public MenuPanel() { 
    this.mf = mf; 

    Dimension size = getPreferredSize(); 
    size.width = 600; 
    size.height = 600; 
    setPreferredSize(size); 

    ImageIcon menuIcon = new ImageIcon("C:\\Programming\\NetBeansProjects\\PDCMain\\src\\Data\\the_menu_title2.png"); 
    JLabel menuLbl = new JLabel(); 
    menuLbl.setIcon(menuIcon); 

    JButton newGameBtn = new JButton("New Game"); 
    JButton loadGameBtn = new JButton("Load Game"); 
    JButton helpBtn = new JButton("Instructions"); 
    JButton exitBtn = new JButton("Exit"); 

    newGameBtn.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      System.out.println("New Game"); 
      mf.changePanel("gamePanel"); 
     } 
    }); 

loadGameBtn.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 

     } 
    }); 

    helpBtn.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      showHelp(); 
     } 
    }); 

    exitBtn.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      System.exit(0); 
     } 
    }); 


    setLayout(new GridBagLayout()); 

    GridBagConstraints gc = new GridBagConstraints(); 

    gc.weightx = 0; 
    gc.weighty = 0.1; 

    gc.gridx = 0; 
    gc.gridy = 1; 
    add(menuLbl, gc);   

    gc.gridx = 0; 
    gc.gridy = 2; 
    add(newGameBtn, gc); 

    gc.gridx = 0; 
    gc.gridy = 3; 
    add(loadGameBtn, gc); 

    gc.gridx = 0; 
    gc.gridy = 4; 
    add(helpBtn, gc); 

    gc.gridx = 0; 
    gc.gridy = 5; 
    add(exitBtn, gc); 

} 

public void showHelp(){ 
    String[] help = new String[100]; 
    try { 
     BufferedReader br = new BufferedReader(new FileReader("instruct.txt")); 
     String line = ""; 
     int i = 0; 
     while((line = br.readLine()) != null) { 
      help[i] = line; 
      i++; 
     } 
     JOptionPane.showMessageDialog(null, help); 
    } catch(IOException ex) { 
     System.err.println("IOException Error: " + ex.getMessage()); 
    } 
} 

,這裏是遊戲盤

public class GamePanel extends JPanel{ 

private ButtonsPanel buttonsPanel; 
private GraphicsPanel graphicsPanel; 
private final JPanel gamePanel; 

public GamePanel(){ 

    super(); 
    this._initGUI(); 

    gamePanel = new JPanel(); 
    Dimension size = getPreferredSize(); 
    size.width = 600; 
    size.height = 600; 
    setPreferredSize(size); 
    setBackground(Color.RED); 

} 
private void _initGUI(){ 

    this.buttonsPanel = new ButtonsPanel(); 
    this.graphicsPanel = new GraphicsPanel(); 

    this.setLayout(new BorderLayout()); 
    this.add(buttonsPanel, BorderLayout.SOUTH); 
    this.add(graphicsPanel, BorderLayout.CENTER); 
} 

public void run(){ 
    graphicsPanel.run(); 
} 

}

這是我從頭開始建立一個圖形用戶界面和使用cardlayout第一次嘗試。我看不出哪裏會分配一個空值作爲面板被用於切換主面板宣佈,任何想法?

+0

爲了更好地爲您提供幫助,請在[M CVE](http://stackoverflow.com/help/mcve)(最小完整可驗證示例),而不是三個源文件。 – 2014-10-20 06:36:50

+0

*「..得到一個nullpointerException。」* 1)請參閱[什麼是堆棧跟蹤,以及如何使用它來調試我的應用程序錯誤?](http://stackoverflow.com/q/3988788/418556)& [什麼是空指針異常,以及如何解決它?](http://stackoverflow.com/q/218384/418556)2)總是複製/粘貼錯誤和異常輸出! – 2014-10-20 06:38:20

+0

當我嘗試運行你的代碼時,我得到一個(基本上)空白的屏幕,因爲沒有添加按鈕 – MadProgrammer 2014-10-20 06:41:42

回答

3

花一秒鐘看一下這段代碼...

public static class MenuPanel extends JPanel { 

    MainFrame mf; 

    public MenuPanel() { 
     this.mf = mf; 

基本上,你正在分配(thismfthis.mf,但由於mf已經nullthis.mf仍將null ...

你應該傳遞的MainFrame參考,您MenuPanel

現在,因爲我討厭身邊的UI組件的引用傳遞給程序的其他部分,這應該沒有關於用戶界面的其他想法,做對他們沒有直接的控制,我會建議反對通過MainFrame致盲這樣。

相反,創建一個interface提供您預計MenuPanel應該被允許執行功能(newGameloadGameshowInstructionsexit),例如,允許該interface(可能是MainFrame)的實施來對付它

然後,您可以通過這個接口來MenuPanel實例......這限制類與其他類的曝光,其並不需要這些類的功能和解耦你的代碼,以便您可以通過該接口的任何舊實例的而不必重寫代碼的整個部分...

有一個基本的概念

開始以某種遊戲控制器接口,例如更新...

這說明,可以採取針對該接口的實現的行動。

使用MainFrame貫徹GameController ...

public class MainFrame extends JPanel implements GameController { 

    //... 

    public void newGame() { 
    } 

    public void loadGame() { 
    } 

    public void showInstructions() { 
    } 

    public void exit() { 
    } 

變化MenuPane時,它的構造需要GameController實例...

public class MenuPanel extends JPanel { 

    private GameController controller; 

    public MenuPanel(GameController gameController) { 
     this.controller = gameController; 
     //... 

現在,當你處理用戶交互,你會請求傳遞給控制器​​....

newGameBtn.addActionListener(new ActionListener() { 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     System.out.println("New Game"); 
     controller.newGame(); 
    } 
}); 

這種方式,MenuPanel不知道如何在新的遊戲中創建的,它只是知道它會被照顧...

現在,你將需要更新newGame方法MainFrame做一些事情,比如......

public void newGame() { 
    // Setup the new game... 
    cl.show(mainPanel, "gamePanel"); 
} 

這會將所有的責任正好與實施GameController做決定如何某些動作應該發生,將進程分離,所以如果你將GameController的實現更改爲某個其他類,則不必擔心更新MenuPanel,因爲它僅對GameController感興趣......不錯;)

+0

對不起,我在之前版本的代碼中工作過,但由於它變得混亂,我又開始了。我很困惑如何實現接口,什麼是最好的方式來傳遞MainFrame ..主要是我可以測試graphicsPanel工作,公共MenuPanel(大型機主機)等? – user2797454 2014-10-20 06:53:17

+0

不,你並沒有在'MenuPanel'中創建一個'MainFrame'的新實例,你也傳遞了一個引用,所以你最終得到'NullPointerException',因爲'MenuPanel'中的'mf'是'null',它從來沒有分配一個有效的值... – MadProgrammer 2014-10-20 06:55:35

+0

感謝您的幫助和解釋,我會看到我如何去執行這個 – user2797454 2014-10-20 07:24:31