gpt4 book ai didi

java - Swing CardLayout 的问题

转载 作者:行者123 更新时间:2023-12-01 22:39:00 24 4
gpt4 key购买 nike

我正在构建一个 Java 虚拟宠物游戏,当前菜单面板工作正常,按钮正在加载和操作,但是当我单击本应启动到 GamePanel 面板的新游戏按钮时,我收到 nullpointerException。

这是构建原始框架和要切换的 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();
}

}

这是我第一次尝试从头开始构建 GUI 并使用卡片布局。我看不到它将在哪里分配空值,因为面板是在用于切换的主面板中声明的,有什么想法吗?

最佳答案

花点时间看看这段代码...

public static class MenuPanel extends JPanel {

MainFrame mf;

public MenuPanel() {
this.mf = mf;

基本上,您正在分配 ( this ) mfthis.mf ,但自从 mf已经是null , this.mf将保持null ...

您应该传递 MainFrame 的引用给您MenuPanel

现在,因为我讨厌将 UI 组件的引用传递给程序的其他部分,而程序的其他部分应该不知道 UI 的其余部分并且不直接控制它们,所以我建议不要传递 MainFrame像这样让人眼花缭乱。

相反,创建一个 interface它提供了您期望的功能 MenuPanel应该允许执行( newGameloadGameshowInstructionsexit ),并允许执行此 interface (可能是 MainFrame )来处理它

然后您可以将此接口(interface)的实例传递给 MenuPanel ...这限制了类对不需要这些类功能的其他类的暴露,并解耦了您的代码,以便您可以将接口(interface)的任何旧实例传递给类,而无需重写代码的整个部分...

更新了基本概念

从某种游戏 Controller 界面开始,例如......

public interface GameController {

public void newGame();
public void loadGame();
public void showInstructions();
public void exit();

}

这描述了针对此接口(interface)的实现可以采取的操作。

使用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;
//...

现在,当您处理用户交互时,您会将请求传递给 Controller ​​......

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 的实现完全 Hook 。决定如何进行某些操作,使流程解耦,因此如果您更改 GameController 的实现对于其他一些类,您无需担心更新 MenuPanel ,因为它只对 GameController 感兴趣。 ...很好;)

关于java - Swing CardLayout 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26459688/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com