3

I'm trying to dynamically update a JComboBox in swing application and getting a null pointer exception.

class Accounts extends JPanel {

    JComboBox<String> accountSelect;
    DefaultComboBoxModel accountSelectModel;
  public Accounts() {
    this.initGUI();
  }
  public void initGUI() {
   //setLayout etc...
    String[] al = {};//start empty
   this.accountSelectModel = new DefaultComboBoxModel(al);
    this.accountSelect = new JComboBox<String>();
     this.accountSelect.setModel(accountSelectModel);
    this.add(this.accountSelect);
 }
 public void updateComboBox(String[] al) {
  //clear items and apply new
  this.accountSelectModel = new DefaultComboBoxModel(al);
  this.accountSelect.setModel(this.accountSelectModel);
 }

 public void removeComboBoxItems() {
    //A call HERE here resorts in a null exception pointer ???
    this.accountSelectModel.removeAllElements();
   }

 }

Thanks for any feedback.

UPDATE

Figured out the problem. Initially I was very sure this wasn't the problem (sorry for not putting in this code).

I was initially adding listener via addActionListener (inside Accounts) to the accountSelect combobox.

  this.accountSelect.addActionListener(new AcountActionListener);

class AcountSelectListener implements ActionListener {
   void actionPerformed(ActionEvent e) P
    //Object source etc..
    if(source == accountSelect) {
      //etc...
      selectAccount(item);
    }
  }

}

Instead, I'm doing:

class Accounts extends JPanel implements ActionListener 

and overriding the actionPerformed method inside the Accounts.

this solved my issue...

UPDATE 2

However, I would prefer (as well as what others have recommended) I don't have to make entire Accounts class ActionListener.

So I went to original and found the problem was each call to this.accountSelectModel.removeAllElements triggered an action in the inner AccountSelectListener that was added to this.accountSelect.

The listener was meant to set the new combo box option, but since it wasn't called at the time a select change occurred (but on removeAllElements), the object source (item) was null which when passed threw the NPE.

  • 6
    Per my review, your posted code is not showing the reason for the NPE suggesting that its source lies elsewhere. Let's see the calling code, the code that calls the `removeComboBoxItems()` method. Is it calling it on a valid Accounts instance? Also, as an aside, consider using a little less `this`. It can make your code unnecessarily wordy.\ – Hovercraft Full Of Eels May 04 '13 at 17:28
  • Yes, its a valid instance of Accounts, its actually the statement to removeAllElements causing the issue, anything else such as "System.out.println" etc... it works just fine. And if it wasn't a valid instance, I wouldn't be able to call updateComboBox. –  May 04 '13 at 18:47
  • My guess is it maybe a repaint issue on the EDT after I update... –  May 04 '13 at 18:49
  • Coming from a C++ background, I prefer using the keyword this. –  May 04 '13 at 18:52
  • 1
    @HovercraftFullOfEels asks, "So how can it ever be `null` based on the code above?" The default value is `null`; I'm guessing that constructing `Accounts` on the [*initial thread*](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html) will race a listener running on the EDT. Moreover, `initGUI()` is `public` and may be called anytime – trashgod May 04 '13 at 20:59
  • solved the issue, see my update. –  May 04 '13 at 22:08
  • thanks for the help though, everyones comments always point me in the right direction. –  May 04 '13 at 22:08
  • 1
    I knew that the problem couldn't be in the code you initially posted but I'm still not sure how the newly posted code causes the problem. Your solution may not be a good one as you shouldn't have GUI classes implementing listener interfaces unless you're working on a very simple toy program as it gives the class too much responsibility which can lead to too much coupling and not enough cohesion. – Hovercraft Full Of Eels May 04 '13 at 22:25
  • Do you have a solution in that case? –  May 05 '13 at 01:10
  • 2
    @lcplusplus: impossible to say. You've not defined the problem well enough for us to give a solution. You have not shown the reason for the NPE yet. Using an outside listener class does not by itself cause a NPE to occur, and in fact is commonly done. If you create and post an [sscce](http://sscce.org) that reproduces your problem, Im 99% sure that I can show you a decent solution though. – Hovercraft Full Of Eels May 05 '13 at 02:15
  • 1
    Solved the issue (I have updated my question). Thanks once more for the feedback. –  May 05 '13 at 06:46

1 Answers1

1

Avoid calling public methods in the constructor. In particular, check whether you're calling removeComboBoxItems() from a listener that is added before the Accounts constructor finishes, as might happen if you fail to construct Swing GUI objects on the event dispatch thread. By default, the value of accountSelectModel is null.

As an aside, JComboBox listens to its ComboBoxModel, so you don't have to replace the model; just update it in place.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • I realize now your answer somewhat addressed my issue with the ComboBoxModel listener even though I did not post the relevant code. So I accept your answer with reference to my update 2. –  May 05 '13 at 06:52
  • 1
    Credit also to [Theodoros Chatzigiannakis](http://stackoverflow.com/users/1892179/theodoros-chatzigiannakis) and [Hovercraft Full Of Eels](http://stackoverflow.com/users/522444/hovercraft-full-of-eels) for helpful colloquy; +1 for update. – trashgod May 05 '13 at 15:10