1
votes

I have been trying to get a JComboBox to update when a new item is added to a backend database.

In the actual code there is a separate class that handles an add dialog, when the new item is added it updates the database and then should add the same item to the dropdown menu by calling a method that accepts a String in the main GUI class. (trying to follow Model-View-Controller).

Below is a minimal example that triggers an error although in the actual application it fails silently.

I have an inkling it has to do with instances of objects. Also to populate the list I'm iterating over a list using addItem() to make sure that is working and the ComboBox is Mutable.

Thanks any help Tom

import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class TestComboBox extends JPanel implements ActionListener{

JComboBox moduleList = new JComboBox(new DefaultComboBoxModel());
TestComboBox testComboBox;
JFrame frame;

public void actionPerformed(ActionEvent e){
    if("additem".equals(e.getActionCommand())){
        addItem("Item");
    }
    if("additemfail".equals(e.getActionCommand())){
        testComboBox.addItemFail("Item Fail");
    }
}

public void addItem(String item){
    moduleList.addItem(item);
}

public void addItemFail(String item){
    testComboBox = new TestComboBox();
    moduleList.addItem(item);
}


protected JPanel createPanel(){
    JPanel panel = new JPanel(false);

    String[] getModuleList = {"MODULE 1", "MODULE 2"};
    moduleList = new JComboBox(new DefaultComboBoxModel(getModuleList));
    panel.add(moduleList);

    JButton additem = new JButton("Add Item");
    additem.setActionCommand("additem");
    additem.addActionListener(this);
    panel.add(additem);

    JButton additemfail = new JButton("Add Item Fail");
    additemfail.setActionCommand("additemfail");
    additemfail.addActionListener(this);
    panel.add(additemfail);

    return panel;
}

public void createAndShowGui(){
    testComboBox = new TestComboBox();
    frame = new JFrame("JComboTest");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    frame.add(testComboBox.createPanel());
    frame.setSize(450, 150);
    frame.setVisible(true);
}

public static void main(String[] args){
    TestComboBox t = new TestComboBox();
    t.createAndShowGui();
}
}

Exception that is thrown

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at TestComboBox.actionPerformed(TestComboBox.java:16)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2012)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2335)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:404)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:253)
    at java.awt.Component.processMouseEvent(Component.java:6268)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
    at java.awt.Component.processEvent(Component.java:6033)
    at java.awt.Container.processEvent(Container.java:2045)
    at java.awt.Component.dispatchEventImpl(Component.java:4629)
    at java.awt.Container.dispatchEventImpl(Container.java:2103)
    at java.awt.Component.dispatchEvent(Component.java:4455)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4633)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4297)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4227)
    at java.awt.Container.dispatchEventImpl(Container.java:2089)
    at java.awt.Window.dispatchEventImpl(Window.java:2517)
    at java.awt.Component.dispatchEvent(Component.java:4455)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:649)
    at java.awt.EventQueue.access$000(EventQueue.java:96)
    at java.awt.EventQueue$1.run(EventQueue.java:608)
    at java.awt.EventQueue$1.run(EventQueue.java:606)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:105)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:116)
    at java.awt.EventQueue$2.run(EventQueue.java:622)
    at java.awt.EventQueue$2.run(EventQueue.java:620)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:105)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:619)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)
2
row 16 is testComboBox = new TestComboBox();, for why hells on the world ..., you recreate class again, from itselfmKorbel
The problem is a null variable. The error message tells you which line is causing the problem. So look at all the variable used on the line and determine which one is null. Then you need to change the code to make sure the variable isn't null when you try to access it.camickr

2 Answers

1
votes

Instead of testComboBox.addItemFail("Item Fail");, you should simply call addItemFail("Item Fail"); in your actionPerformed method.

Edit: And you should not recreate object of same class again in addItemFail method (whats the point of doing it again?)

1
votes

Your problem is that your class creates another class instance of itself inside itself. First you create a TestComboBox(TCB) with a link to another TestCombobox which is Null as you haven't set it to anything else anywhere.

The first TCB (A) is your t with a null TCB link, created in main().

This TCB link is set by creating a new TCB (B) (which incidently contains another null tcb link) in createAndShowGui(). This one is also the one which gets all the panels and also all the listeners.

So when you press that button in the panel the actionevent is fired and picked up by B as it is the only one with the listeners. But then it tries to access the TCB link in B which is null causing the nullpointerexception.

Adding even more confusion is the fact that your addItemFail creates yet another TCB which gets added to B.

My suggestion to you is to rethink and redesign this. It's way too confusing at the moment. Furthermore there are not a single comment in the code which makes the original intent behind the code even harder to understand. You will want to get rid of all new creations of TCB creation inside the class.