2009-02-22 2 views
1

G'day all,Сложность удаления всех компонентов из Jpanel

Я кодирую главное меню для проекта. Меню отображается правильно. Я также создал 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); 
    } 
} 

Вот мой 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 
      } 
     } 
    } 

ответ

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

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

1

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

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

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

+0

Спасибо Зак. Я буду рассматривать CardLayout. – elwynn

0

Не пытайтесь «повторно использовать» материал. Компьютеры вполне способны убирать. Сосредоточьтесь на том, чтобы сделать код понятным.

Поэтому вместо того, чтобы пытаться убрать панель, просто замените ее на новую.

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

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

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

public static void main(final String[] args) { 
    java.awt.EventQueue.invokeLater(new Runnable() { public void run() { 
     runEDT(); 
    }}); 
}