Search code examples
javaswingactionlistenerjcombobox

java - Refreshing JComboBox throws exception


I have a combobox using a model with a listener attached to catch the selected item:

deleteCombo = new JComboBox<Course>(course.toArray(new Course[course.size()]));
model = new DefaultComboBoxModel<Course>( course.toArray(new Course[course.size()]) );
deleteCombo.setModel( model );
deleteCombo.setRenderer(renderer);
deleteCombo.setSelectedIndex(0);
deleteCombo.addActionListener( new ActionListener() {

    public void actionPerformed(ActionEvent e)
    {
        JComboBox deleteCombo = (JComboBox)e.getSource();
        Course course = (Course)deleteCombo.getSelectedItem();
        deleteNumTxt.setText( course.getCourseNum() ); //This is line 391
        deleteTitleTxt.setText( course.getCourseTitle() );
        deleteDurationTxt.setText( String.valueOf(course.getDuration() ) );
        deleteFeeTxt.setText("$" + String.valueOf(course.getCourseFee() ) );
        deleteLevelTxt.setText( course.getCourseLevel() );
    }
});

I'm using the itemSelected event to populate textfields in the GUI to show the details of the course selected. When the course is selected and the Delete Course button is clicked it goes to this method:

public static void deleteCourseRecord() {
courseNumIn = deleteNumTxt.getText();
int index = course.indexOf(new Course(courseNumIn));
course.remove(index);

//RE-POPULATE EDIT AND DELETE COMBOBOXES
model.removeAllElements();
for(Course item : course) {
    model.addElement(item);
    }
}

The record gets deleted but it throws this exception:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at MyCourse$2.actionPerformed(MyCourse.java:391)
at javax.swing.JComboBox.fireActionEvent(JComboBox.java:1260)
at javax.swing.JComboBox.contentsChanged(JComboBox.java:1331)
at javax.swing.JComboBox.intervalRemoved(JComboBox.java:1351)
at javax.swing.AbstractListModel.fireIntervalRemoved(AbstractListModel.java:179)
at javax.swing.DefaultComboBoxModel.removeAllElements(DefaultComboBoxModel.java:175)
at MyCourse$Course.deleteCourseRecord(MyCourse.java:1138)
at MyCourse.actionPerformed(MyCourse.java:883)
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)
tjavax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)

I think there is a problem in the way I've got the actionPerformed section constructed, but I don't know what it is. If I don't refresh the combo box with the model (or any other method) it doesn't throw the exception.If I comment out line 391 (marked in the code) it will throw the exception on line 392 and so on. If all the lines of code that are populating the textfields are commented out it throws no exception but, of course, the function is lost. Any ideas on what I'm doing wrong? Cheers


Solution

  • The problem is as follows:

    Everytime you change the model that is set to the combo box the action listener is called.

    So when you do this:

    //RE-POPULATE EDIT AND DELETE COMBOBOXES
    model.removeAllElements();
    

    The actionlistener is executed and

    Course course = (Course)deleteCombo.getSelectedItem();
    

    is null, since you just removed all elements from your combobox.

    You can see this if you try this simple example:

    public static void main(String[] args) 
        String [] s = {"1", "2"};
        DefaultComboBoxModel<String> model = new DefaultComboBoxModel<String>(s);
        JComboBox<String> j = new JComboBox<String>(s);
        j.setModel(model);
    
        j.addActionListener(new ActionListener() {
    
            @Override
            public void actionPerformed(ActionEvent arg0) {
                System.out.println(((JComboBox) arg0.getSource()).getSelectedItem());               
            }
        });
    
        JFrame jf = new JFrame();
        jf.add(j);
        jf.setVisible(true);
        jf.setSize(100, 100);
    
        model.removeAllElements();
    }
    

    It will output null.