Сложность удаления всех компонентов из Jpanel - PullRequest
1 голос
/ 22 февраля 2009

G'day all,

Я кодирую главное меню для проекта. Меню отображается правильно. Я также настроил ActionListeners для трех кнопок в меню.

Что я хочу сделать, это повторно использовать JPanel для нового набора переключателей, когда пользователь выбирает «Начать новую игру».

Однако кодирование ActionPerformed для удаления существующих компонентов из JPanel поставило меня в тупик. Я знаю, что removeAll как-то важно, но, к сожалению, NetBeans сообщает мне, что я не могу вызвать его на своем объекте mainMenu JPanel в ActionPerformed. Поэтому я прокомментировал это в своем коде ниже, но оставил его, чтобы вы могли видеть, что я пытаюсь сделать.

Ваши мысли или подсказки приветствуются.

Вот мой основной код:

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
            }
        }
    }

Ответы [ 5 ]

2 голосов
/ 22 февраля 2009

Попробуйте вместо этого использовать CardLayout, который управляет двумя или более компонентами (обычно JPanel экземплярами), которые совместно используют одно и то же пространство отображения. Таким образом, вам не нужно возиться с добавлением и удалением компонентов во время выполнения.

1 голос
/ 22 февраля 2009

Вам необходимо, чтобы 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();

Почему вы чувствуете необходимость повторно использовать этот объект?

1 голос
/ 22 февраля 2009

У вас нет ссылки на mainMenu actionPerformed use. Если вы объявите mainMenu с помощью кнопок. Это будет работать.

0 голосов
/ 22 февраля 2009

Старайтесь не пытаться «повторно использовать» вещи. Компьютеры вполне способны привести в порядок. Сконцентрируйтесь на разъяснении своего кода.

Так что вместо того, чтобы пытаться убрать панель, просто замените ее новой.

Как правило, лучший способ написать слушателей - это анонимные внутренние классы. Код внутри них будет иметь доступ к конечным переменным во вложенной области видимости и к членам включающего класса. Итак, если вы сделаете mainMenu final и у вас ActionListener анонимные внутренние классы, ваш код должен хотя бы скомпилироваться.

Также не пытайтесь повторно использовать классы. Постарайтесь заставить каждый класс делать одну разумную вещь и избегать наследования (реализации). Почти никогда не нужно расширять JFrame, так что не делайте этого. Создайте ActionListener для каждого действия, а не пытайтесь определить источник события.

Также обратите внимание, что вы всегда должны использовать компоненты Swing в потоке диспетчеризации событий AWT. Измените метод main, чтобы добавить шаблон как:

public static void main(final String[] args) {
    java.awt.EventQueue.invokeLater(new Runnable() { public void run() {
        runEDT();
    }});
}
0 голосов
/ 22 февраля 2009

Проблема в том, что метод 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();
    }
}
...