1

万事如意,

我正在为一个项目编写一个主菜单。菜单正确显示。我还为菜单上的三个按钮设置了 ActionListener。

我希望做的是在用户选择“开始新游戏”时将 JPanel 重用于一组新的单选按钮。

但是,编写 ActionPerformed 以从 JPanel 中删除现有组件让我感到困惑。我知道 removeAll 在某种程度上很重要,但不幸的是 NetBeans 告诉我我不能在 ActionPerformed 内的 mainMenu JPanel 对象上调用它。因此,我在下面的代码中将其注释掉了,但将其保留了下来,以便您可以看到我要做什么。

感谢您的想法或提示。

这是我的主要代码:

public class Main {

    public static void main(String[] args) {
        MainMenu menu = new MainMenu();
        menu.pack();
        menu.setVisible(true);
    }
}

这是我的主菜单代码:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

    public class MainMenu extends JFrame implements ActionListener {
        JButton startNewGame = new JButton("Start a New Game");
        JButton loadOldGame = new JButton("Load an Old Game");
        JButton seeInstructions = new JButton("Instructions");

        public MainMenu() {
            super("RPG Main Menu");
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JPanel mainMenu = new JPanel();
            mainMenu.setLayout(new FlowLayout());
            startNewGame.setMnemonic('n');
            loadOldGame.setMnemonic('l');
            seeInstructions.setMnemonic('i');
            startNewGame.addActionListener(this);
            loadOldGame.addActionListener(this);
            seeInstructions.addActionListener(this);
            mainMenu.add(startNewGame);
            mainMenu.add(loadOldGame);
            mainMenu.add(seeInstructions);
            setContentPane(mainMenu);

        }

        public void actionPerformed(ActionEvent evt) {
            Object source = evt.getSource();
            if (source == startNewGame) {
                // StartNewGame code goes here
                // mainMenu.removeAll();
            }
            if (source == loadOldGame) {
                // LoadOldGame code goes here
            }
            if (source == seeInstructions) {
                // Quit code goes here
            }
        }
    }
4

5 回答 5

2

考虑改用 a ,它管理共享相同显示空间的CardLayout两个或多个组件(通常是实例)。JPanel这样您就不必在运行时添加和删除组件。

于 2009-02-22T07:15:43.300 回答
1

您没有参考 mainMenu actionPerformed 使用。如果您使用按钮声明 mainMenu。它会起作用的。

于 2009-02-22T07:12:54.180 回答
1

您需要 mainMenu 成为成员变量:

 public class MainMenu extends JFrame implements ActionListener {
        JButton startNewGame = new JButton("Start a New Game");
        JButton loadOldGame = new JButton("Load an Old Game");
        JButton seeInstructions = new JButton("Instructions");
        JPanel mainMenu = new JPanel();

为什么你觉得有必要重新使用这个对象?

于 2009-02-22T07:13:04.040 回答
0

问题是该actionPerformed方法试图调用JPanel mainMenu超出范围的方法,即该mainMenu变量在该方法中不可见actionPerformed

解决此问题的一种方法是JPanel mainMenu在类本身中声明并使其成为类的所有实例方法都可以访问的实例字段。

例如:

public class MainMenu extends JFrame implements ActionListener
{
    ...
    JPanel mainMenu;

    public MainMenu()
    {
        ...
        mainMenu = new JPanel();
        ...
    }

    public void actionPerformed(ActionEvent e)
    {
        ...
        mainMenu.removeAll();
    }
}
于 2009-02-22T07:13:51.977 回答
0

避免尝试“重用”东西。计算机非常有能力整理。专注于使您的代码清晰。

因此,与其尝试整理面板,不如用一个新面板替换它。

通常,编写侦听器的更好方法是匿名内部类。其中的代码将可以访问封闭范围内的最终变量和封闭类的成员。所以,如果你 make mainMenufinal 并且你ActionListener是匿名内部类,你的代码至少应该编译。

也不要尝试“重用”类。尽量让每个类做一件明智的事情,并避免继承(实现)。几乎没有任何需要 extend JFrame,所以不要那样做。为每个操作创建一个ActionListener,而不是尝试确定事件源。

另请注意,您应该始终在 AWT 事件调度线程上使用 Swing 组件。更改main方法以添加样板文件,例如:

public static void main(final String[] args) {
    java.awt.EventQueue.invokeLater(new Runnable() { public void run() {
        runEDT();
    }});
}
于 2009-02-22T11:54:35.017 回答