tomwj
tomwj

Reputation: 46

Adding item to JComboBox from different class

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)

Upvotes: 1

Views: 2980

Answers (2)

Steinin
Steinin

Reputation: 541

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.

Upvotes: 1

Usman Saleem
Usman Saleem

Reputation: 1655

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?)

Upvotes: 1

Related Questions