2014-10-17 4 views
0

Привет, я работаю над проектом, где мне нужно было создать игру CUI и теперь преобразовать ее в GUI, я в процессе добавления функциональности кнопки, взаимодействующие с игрой, но у меня проблемы ,Java Swing actionPerformed

Это метод, к которому я пытаюсь получить доступ. Это в классе под названием Pet.

public double feedPet() { 

    if(this.hunger < MAX_HUNGER) { 
     this.hunger += food; 
      if(this.hunger > MAX_HUNGER) { 
       this.hunger = MAX_HUNGER; 
      } 
     System.out.println(this.petName + " enjoyed the meal!"); 
     System.out.println("Hunger increased by " + food + " to a total of " + this.hunger); 
     spacing(); 
    } 
    else { 
     System.out.println(this.petName + " is currently full!"); 
     spacing(); 
    } 

    return this.hunger; 
} 

Это класс, который пытается получить доступ к методу.

public GamePanel(PetWorld petWorld, Pet pet, Game game) { 
    initComponents(); 
    genComponents(pet); 
} 

private void genComponents(final Pet pet) { 


    this.setSize(600, 600); 

    graphicsPanel.setSize(600, 400); 
    graphicsPanel.setBackground(Color.red); 

    buttonPanel.setSize(600, 200); 

    buttonPanel.setBorder(BorderFactory.createTitledBorder("Pet Options")); 

    JButton feedBtn = new JButton("Feed"); 
    JButton playBtn = new JButton("Play"); 
    JButton sickBtn = new JButton("Medicine"); 
    JButton trainBtn = new JButton("Train"); 
    JButton sleepBtn = new JButton("Sleep"); 

    //// error occurring here I believe \\\\ 
    feedBtn.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      pet.feedPet(); 
     } 
    }); 

    buttonPanel.setLayout(new GridBagLayout()); 

    GridBagConstraints gc = new GridBagConstraints(); 

    //// Pet Options \\\\ 
    gc.weightx = 0.5; 
    gc.weighty = 0.5; 

    gc.gridx = 0; 
    gc.gridy = 1; 
    buttonPanel.add(feedBtn, gc); 

    gc.gridx = 1; 
    gc.gridy = 1; 
    buttonPanel.add(playBtn, gc); 

    gc.gridx = 2; 
    gc.gridy = 1; 
    buttonPanel.add(sickBtn, gc); 

    gc.gridx = 3; 
    gc.gridy = 1; 
    buttonPanel.add(trainBtn, gc); 

    gc.gridx = 4; 
    gc.gridy = 1; 
    buttonPanel.add(sleepBtn, gc);   

}

Я должен был сделать окончательное животное, я считаю, что это плохо, как я изменить значение в самом любимце, например, счастье, голод и т.д.

ошибка, которую я я нажимаю кнопку

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
    at pdcmainGUI.GamePanel$1.actionPerformed(GamePanel.java:63) 
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018) 
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341) 
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402) 
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259) 
    at  javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252) 
    at java.awt.Component.processMouseEvent(Component.java:6505) 
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3320) 
    at java.awt.Component.processEvent(Component.java:6270) 
    at java.awt.Container.processEvent(Container.java:2229) 
    at java.awt.Component.dispatchEventImpl(Component.java:4861) 
    at java.awt.Container.dispatchEventImpl(Container.java:2287) 
    at java.awt.Component.dispatchEvent(Component.java:4687) 
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832) 
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492) 
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422) 
    at java.awt.Container.dispatchEventImpl(Container.java:2273) 
    at java.awt.Window.dispatchEventImpl(Window.java:2719) 
    at java.awt.Component.dispatchEvent(Component.java:4687) 
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:735) 
    at java.awt.EventQueue.access$200(EventQueue.java:103) 
    at java.awt.EventQueue$3.run(EventQueue.java:694) 
    at java.awt.EventQueue$3.run(EventQueue.java:692) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at  java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) 
    at  java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87) 
    at java.awt.EventQueue$4.run(EventQueue.java:708) 
    at java.awt.EventQueue$4.run(EventQueue.java:706) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at  java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) 
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:705) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138) 
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91) 

Есть ли лучший способ реализовать то, что я пытаюсь сделать? Я предполагаю, что это вызвано методом, пытающимся изменить значения переменных, но будучи установленным в final в классе gui? Любые предложения оценены.

+1

Ну, довольно очевидно, что 'pet' является' null', вопрос в том, почему, но недостаточно контекста, чтобы быть уверенным на 100%. Рассмотрите возможность предоставления [runnable example] (https://stackoverflow.com/help/mcve), который демонстрирует вашу проблему. Это приведет к меньшему путанице и лучшим ответам – MadProgrammer

+0

вам следует предоставить код класса, который создает экземпляр GamePanel –

ответ

1

Проблема связана с вашей декларацией слушателя действий. Пока вы создаете ActionListener() внутри процедуры genComponents (конечная Pet pet), это не то место, где она выполняется во время выполнения.

Но сначала давайте также очистить вызов переменной как final. Что это означает, что это pet не может быть переведен на другую любимца, это не значит, что вы не можете получить доступ к методам вашего pet, которые могут изменяться, например, isHungry(), setFed (логическое) и т.д.

Во-вторых, получите ваш pet в объем. Когда вы определите процедуру genComponents(final Pet pet), pet находится в области видимости, поэтому компилятор java не имеет проблем во время компиляции. Но во время выполнения выполняется процедура genComponents(final Pet pet) с известным pet, и во время этого выполнения он создает ActionListener, что указывает на местоположение переменной для параметра. По завершении процедуры genComponents(...) параметр выходит за рамки. Когда ActionListener запускается нажатием кнопки, он пытается ссылаться на ячейку памяти переменной вне области видимости.

private void genComponents(final Pet pet) { 

    .... 

    feedBtn.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      pet.feedPet(); <-- pet refers to the parameter, but it is out of scope when this gets executed. 
     } 
    }); 

    .... 
} 

Решение пространства: Для того, чтобы решить эту проблему, в pet должно быть доступно где-то в области видимости, и вы можете сделать это, просто хранить pet как переменные частный класс.

public class GamePanel { 

    private final Pet pet; 

    public GamePanel(PetWorld petWorld, Pet pet, Game game) { 
     this.pet = pet; 
     initComponents(); 
     genComponents(); <-- remove the pet parameter 
    } 

    private void genComponents() { 
     .... 

     feedBtn.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       pet.feedPet(); <-- this pet now refers to the class variable, which is still in scope. 
      } 
     }); 

     .... 
    } 
} 
+0

Спасибо за ваш ответ, не могу поверить, что я окончательно смутился. Я решил перезапустить свой проект и сделать гораздо более ясные проблемы, возникшие из-за повторного использования моей старой игры. Не стесняйтесь совета, еще раз спасибо! – theHussle