2015-07-15 5 views
-2

У меня есть класс, который реализует макет карты:NullPointerException в приложении Java Swing-

CardWindow.java

import java.awt.CardLayout; 
import java.awt.EventQueue; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

import extraction.gui.Diagram; 
import extraction.main.Main; 

public class CardWindow extends JPanel{ 

/** 
* 
*/ 
private static final long serialVersionUID = 1L; 
private JFrame f; 
private JPanel panel_1, panel_2; 
private JButton btnNext, btnBack; 

/** 
* Launch the application. 
*/ 
public static void main(String[] args) { 
    EventQueue.invokeLater(new Runnable() { 
     public void run() { 
      try { 
       CardWindow window = new CardWindow(); 
       window.f.setVisible(true); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }); 
} 

/** 
* Create the application. 
*/ 
public CardWindow() { 
    initialize(); 
} 

/** 
* Initialize the contents of the frame. 
*/ 
private void initialize() { 
    f = new JFrame(); 
    f.setBounds(100, 100, 1000, 480); 
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    f.getContentPane().setLayout(new CardLayout(0, 0)); 

    panel_1 = new Main_1(); 
    panel_2 = new Snd(); 
    f.getContentPane().add(panel_1); 
    f.getContentPane().add(panel_2); 
    panel_1.setVisible(true); 
    panel_2.setVisible(false); 

    btnNext = new JButton("Next"); 
    btnNext.setBounds(829, 417, 161, 29); 
    panel_1.add(btnNext); 
    btnNext.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      panel_1.setVisible(false); 
      panel_2.setVisible(true); 
     } 
    }); 

    btnBack = new JButton("Back"); 
    btnBack.setBounds(919, 5, 75, 29); 
    panel_2.add(btnBack); 
    btnBack.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      panel_2.setVisible(false); 
      panel_1.setVisible(true); 
     } 
    }); 

} 
} 

Main_1.java

import javax.swing.JPanel; 
import javax.swing.JTextField; 
import javax.swing.JButton; 
import javax.swing.JLabel; 


public class Main_1 extends JPanel { 
private JTextField textField; 

/** 
* Create the panel. 
*/ 
public Main_1() { 
    setLayout(null); 

    textField = new JTextField(); 
    textField.setBounds(131, 69, 134, 28); 
    add(textField); 
    textField.setColumns(10); 

    JButton btnCalculate = new JButton("Calculate"); 
    btnCalculate.setBounds(131, 122, 117, 29); 
    add(btnCalculate); 
btnCalculate.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      Calculate cal = new Calculate(textField.getText()); 
     } 
    }); 


} 
} 

Snd.java

import javax.swing.JPanel; 
import javax.swing.JLabel; 


public class Snd extends JPanel { 

/** 
* Create the panel. 
*/ 
public Snd() { 
    setLayout(null); 

    Calculate _cal = new Calculate(); 

    JLabel label = new JLabel("New label"); 
    label.setBounds(180, 120, 61, 16); 
    add(label); 
    label.setText(_cal.getNum().get(0).toString()); 

} 

} 

Calculate.java

import java.util.ArrayList; 
import java.util.List; 


public class Calculate { 

private List<Integer> abc; 

public Calculate() { 

} 

public Calculate(String number) { 
    abc = new ArrayList<Integer>(); 
    int num = Integer.valueOf(number); 
    for (int i=0;i<num;i++) { 
     abc.add(i); 
    } 
System.out.println(abc); 
} 

public List<Integer> getNum() { 
    return abc; 
} 
} 

У меня есть два других JPanel классов: Main_1.java, Snd.java

В принципе, когда я открываю приложение, оно будет показывать Main_1.java. Я ввожу некоторые значения и запускаю что-то в Calculate.java. Затем, когда я нажимаю следующую кнопку btnNext, она должна отображать обработанные данные на следующую карту Snd.java. Но при попытке запустить приложение я получил java.lang.NullPointerException.

NPE на этой линии label.setText(_cal.getNum().get(0).toString());

Ошибка

java.lang.NullPointerException 
at Snd.<init>(Snd.java:18) 
at CardWindow.initialize(CardWindow.java:59) 
at CardWindow.<init>(CardWindow.java:46) 
at CardWindow$1.run(CardWindow.java:33) 
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311) 
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756) 
at java.awt.EventQueue.access$500(EventQueue.java:97) 
at java.awt.EventQueue$3.run(EventQueue.java:709) 
at java.awt.EventQueue$3.run(EventQueue.java:703) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75) 
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726) 
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201) 
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) 
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105) 
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) 
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93) 
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82) 

Я понимаю, почему это дает NPE, но я не знаю, как ее решить. Когда я запускаю программу, я не понимаю, почему она пытается запустить Snd.java, потому что я не нажал ни одной кнопки, чтобы перейти к следующей карточке, которая равна Snd.java.

Это всего лишь примерный пример, который должен показать, чего я хочу достичь. В основном я хочу обработать что-то в Main_1.java и передать данные в Snd.java, где я буду делать еще один процесс.

+2

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

+0

@MadProgrammer ok уже включает примерный пример. – sw2

+0

@vaxquis Нет. Я отлично понимаю, что такое NPE. Я знаю, что вызывает NPE, но это потому, что я не могу исправить это, что я разместил в SO. Вы внимательно прочитали мой вопрос? – sw2

ответ

0

В вашем примере ваша проблема в том, что ваш новый Calculate имеет abc набор для null implicitly; вы не инициализируете его в конструкторе по умолчанию. Так как это null, вы не можете использовать isEmpty() и т. Д. На нем. Используйте надлежащий

private List<Integer> abc = new ArrayList<Integer>(); 

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

+0

Нет. Это не решает проблему и не связано с моей проблемой. Даже если я удалю оператор 'if', он все равно не работает. Проблема заключается в 'label.setText'. Если я удалю этот 'label.setText', тогда попробуйте запустить программу, она работает, и она прекрасно выводится на консоль. – sw2

+0

@ sw2, если вы все еще так уверены, что я ошибался в этом вопросе после того, как 2 других человека дали вам точно такой же ответ, как и я, - подойдите сами. – vaxquis

-1

Это не полный ответ, более указатель в правильном направлении (как обычно) NPEs.

я изменил в Caluclate.java на

import java.util.ArrayList; 
import java.util.List; 

public class Calculate 
{ 
    private final List<Integer> abc = new ArrayList<>(); 

    public Calculate(String number) { 
     abc.clear(); 
     int num = Integer.valueOf(number); 
     for (int i = 0; i < num; i++) { 
      abc.add(i); 
     } 
     System.out.println(abc); 
    } 

    public List<Integer> getNum() { 
     return abc; 
    } 
} 

Основное отличие заключается в том, что

  1. Список после инициализации, то есть вы всегда можете гарантировать, что она существует, когда вы вызываете ваш метод getNum().
  2. Вместо того, чтобы обновлять его (все же возможно, вам не нужно удалять ключевое слово final, если вы хотите, чтобы это было возможно) теперь он использует ArrayList.clear() вместо объявления нового списка.

Некоторые более ноты включают

  • Используя оператор алмазного <>, введенный в Java7
  • Добавлено еще несколько разнос в коде, пусть это дыхание.
  • Удален конструктор, поскольку он ничего не сделал.

Вы будете иметь проблемы с вашим кодом при его использовании, как вы в вашем Snd.java классе.

import javax.swing.JPanel; 
import javax.swing.JLabel; 

public class Snd extends JPanel 
{ 
    /** 
    * Create the panel. 
    */ 
    public Snd() { 
     setLayout(null); 

     Calculate _cal = new Calculate(); 

     JLabel label = new JLabel("New label"); 
     label.setBounds(180, 120, 61, 16); 
     add(label); 
     label.setText(_cal.getNum().get(0).toString()); // problem occurs here 
    } 
} 

Почему? Потому что abc не был инициализирован. Вы должны были вызвать Calculate с его конструктором String. Который вы не были.

-2

В CardWindow.initialize() по линии 59 вы звоните:

panel_2 = new Snd(); 

Это, в свою очередь, приводит к Snd.<init>() на линии 18, которая:

label.setText(_cal.getNum().get(0).toString()); 

Если разбить это на отдельные строки:

label.setText(
    _cal 
    .getNum()  // this returns null 
    .get(0)  // causing a NullPointerException here 
    .toString()); 

Поскольку _cal определяется следующим образом:

Calculate _cal = new Calculate(); 

И конструктор без аргументов для Calculate пуст, оставив List<Integer> abc набор для null.


Как вы это исправим, это зависит от того, какое поведение вы хотите. С первого взгляда это не выглядит так: Calculate должен иметь конструктор без аргументов; возможно, вы должны удалить его и только инициализировать _cal, как только у вас будет номер для передачи.

Поскольку вы говорите, что не хотите звонить по телефону Snd, альтернативой было бы избежать создания экземпляра Snd в CardWindow.initialize().

+0

Любая обратная связь, downvoter? Мой ответ объясняет причину NPE и предлагает некоторые возможные исправления; в чем проблема? – dimo414