Pregunta

Buenas, todo,

Estoy codificar un menú principal para un proyecto. El menú muestra correctamente. También he establecido ActionListeners para los tres botones en el menú.

Lo que quiero hacer es volver a utilizar el JPanel para un nuevo conjunto de botones de radio cuando el usuario elige "iniciar un nuevo juego".

Sin embargo, la codificación ActionPerformed para eliminar los componentes existentes del JPanel me tiene perplejo. Sé removeAll es de alguna manera importante, pero por desgracia NetBeans me informa que no puedo llamar en mi objeto JPanel mainMenu dentro ActionPerformed. Por lo que he comentado que en mi código de abajo, pero dejó en para que pueda ver lo que estoy tratando de hacer.

Sus pensamientos o sugerencias son apreciadas.

Aquí está mi código principal:

public class Main {

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

Aquí está mi código mainMenu:

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
            }
        }
    }
¿Fue útil?

Solución

Es necesario mainMenu a ser una variable miembro:

 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();

¿Por qué siente la necesidad de volver a utilizar este objeto?

Otros consejos

Considere el uso de un CardLayout lugar, lo cual gestiona dos o más componentes (instancias generalmente JPanel) que comparten el mismo espacio de visualización. De esa manera usted no tiene que jugar con agregar y quitar componentes en tiempo de ejecución.

Usted no tiene una referencia al uso mainMenu actionPerformed. Si se declara mainMenu con los botones. Que funcionaría.

El problema es que el método actionPerformed está intentando llamar a la JPanel mainMenu que está fuera de alcance, es decir, la variable mainMenu no es visible desde el método actionPerformed.

Una forma de evitar esto es tener la declaración JPanel mainMenu en la propia clase y convertirlo en un campo de instancia que se puede acceder a todos los métodos de instancia de la clase.

Por ejemplo:

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

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

    public void actionPerformed(ActionEvent e)
    {
        ...
        mainMenu.removeAll();
    }
}

Evitar el intento de "reutilización" cosas. Las computadoras son muy capaces de poner en orden. Concentrarse en hacer que código claro.

Así que en lugar de tratar de poner en orden el panel, simplemente reemplazarlo por uno nuevo.

En general, una mejor manera de escribir los oyentes es como las clases internas anónimas. Código dentro de éstos tendrá acceso a las variables finales en el ámbito de inclusión ya los miembros de la clase envolvente. Por lo tanto, si usted hace las clases internas mainMenu final y le ActionListeners anónimas, el código debe al menos compilar.

Asimismo, no se tratará de "reutilizar" clases. Trate de hacer cada clase hacer una cosa sensata, y evitar la herencia (de aplicación). Casi nunca hay ninguna necesidad de ampliar JFrame, así que no hacer eso. Crear una ActionListener para cada acción, en lugar de intentar determinar el origen del evento.

También tenga en cuenta, siempre se debe usar componentes Swing en el hilo AWT de distribución de eventos. Cambiar el método de main añadir algo repetitivo como:

public static void main(final String[] args) {
    java.awt.EventQueue.invokeLater(new Runnable() { public void run() {
        runEDT();
    }});
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top