0

I am trying to make a functionality for quick search of clients from database on some keystrokes from user, using an editable combobox. What i wanted to have is, user will put in some letters and if those lettters match with some clients, those clients will be remained in the current data model of the combobox.
The code is as follows. Please fix the exception occuring in the code. Thanks in Advance !!

Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Attempt to mutate in notification

import java.util.ArrayList;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;

class ComboSearch extends JFrame implements CaretListener 
{
  private JComboBox mycombo;
  private ArrayList<String> list;
  private DefaultComboBoxModel<String> isolatemodel,model;

 public ComboSearch()
 {
   setSize(400, 400);
   setLayout(null);
   setDefaultCloseOperation(EXIT_ON_CLOSE);
   mycombo=new JComboBox();
   mycombo.setEditable(true);
   mycombo.setBounds(30,30, 350, 50);
   isolatemodel=new DefaultComboBoxModel();
   model=new DefaultComboBoxModel();
   list=new ArrayList();
   add(mycombo);
   mycombo.setModel(isolatemodel);
   ((JTextField)mycombo.getEditor()
      .getEditorComponent()).addCaretListener(this);
   setVisible(true);}

   private void addElements()
   {
    list.add("Rambhau, Vijay Nagar");
    list.add("Surya, Ashok Puri");
    list.add("Mourya, Shahjapur");
    list.add("Kishorji & sons, Bhopal");
    list.add("Fablica & jewels, Itanagar");
    list.add("Guru Kripa,Ujjain");
    list.add("Hariram Nai & Bakes, Indore");
    list.add("Ganesh Sev Bhandar, Harda");
    list.add("Greatsome Higs, Jabalpur");
    list.add("Treks and hains, Nalanda");
    list.add("Tata Indora, Hoshangabad");
    list.add("Paankhai Seth, Madurai");
    list.add("Katappa, Shikara");
    list.add("Gunjan Samosa, Vijay Nagar");
    list.add("Ramesh hustlers , Vijay Nagar");
  }
  public void makeModels()
  {
     addElements();
     list.stream().forEach((client) -> {
        isolatemodel.addElement(client);
     });
   }

  @Override
  public void caretUpdate(CaretEvent e)
  {
    String searchText=((JTextField)mycombo.getEditor()
                          .getEditorComponent()).getText();

    if(!searchText.isEmpty())
    {
        for(int i=0; i<isolatemodel.getSize();i++)
        {
            if(isolatemodel.getElementAt(i).contains(searchText))
            {
                model.removeAllElements();
                model.addElement(isolatemodel.getElementAt(i));
            }
        }
        mycombo.setModel(model);
        mycombo.showPopup();
    }
    else
    {
        mycombo.setModel(isolatemodel);
    }
  }
 }


public class Execute
{
  public static void main(String[] args)
  {
    ComboSearch searchIt=new ComboSearch();
    searchIt.makeModels();
  }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Suraj Malviya
  • 3,685
  • 1
  • 15
  • 22
  • First off, do not set the layout to `null`. That's just asking for issues. Use a [Layout Manager](https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html) instead – Jonah Mar 22 '16 at 19:22
  • I'm also getting an error that there is no `.contains()` method in this if statement `if(isolatemodel.getElementAt(i).contains(searchText))` – Jonah Mar 22 '16 at 19:28
  • I have used Layout manager too. Its not with that :( – Suraj Malviya Mar 22 '16 at 19:29
  • I know, it was just a tip. – Jonah Mar 22 '16 at 19:29
  • Try changing the `.contains()` to a `.equals()` – Jonah Mar 22 '16 at 19:30
  • Thanks for the tip i ll remember that. but i am not having any error with that '.contains(searchText)' method. the '.equals()' wont fullfil the requirement. i want to search charsequences in the current model – Suraj Malviya Mar 22 '16 at 19:32
  • Ahh, alright. Wonder why I'm getting that error. Might be a java version difference. – Jonah Mar 22 '16 at 19:33
  • Java GUIs have to work on different OS', screen size, screen resolution etc. using different PLAFs in different locales. As such, they are not conducive to pixel perfect layout. Instead use layout managers, or [combinations of them](http://stackoverflow.com/a/5630271/418556) along with layout padding and borders for [white space](http://stackoverflow.com/a/17874718/418556). – Andrew Thompson Mar 22 '16 at 20:31

1 Answers1

2
model.removeAllElements();
model.addElement(isolatemodel.getElementAt(i));

and if those lettters match with some clients, those clients will be remained in the current data model

Well, then it doesn't make sense to remove all the items every time you find a match. Then you will only ever have one entry left in the combo box.

You need to remove all the items BEFORE you start your loop processing and then just add back in the elements that match.

IllegalStateException:

You are trying to update the combo box model before processing of the typed event has finished processing.

Wrap the code in the listener in a SwingUtiltities.invokeLater(...) to the code will be executed after all processing has been finished.

Also, you would generally use a DocuementListener to be notified when the text of the editor has changed, not a CaretListener. The user could use the arrow keys to move the caret so there is no need to update the model in that case.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • how your are so sure that i would be having only one entry left for any charsequence input ?? moreover i have tried putting check on the model for its size that if its empty then dont execute removeAll statement. then too i am having the same exception. and yes thanks for the tip of using DocumentListener. – Suraj Malviya Mar 22 '16 at 19:40
  • Well each time before you add a new element, you clear the list, removing any previously added items. You do this over and over until the very last one where clear is called, then you add one element and the for loop is exited – Jonah Mar 22 '16 at 19:44
  • `if(model.getSize!=0){model.removeAllElements();} model.addElement(isolatemodel.getElementAt(i));` this is what can be done for ensuring that the model is not in illegeal state to be operated ? – Suraj Malviya Mar 22 '16 at 19:48
  • yeah i got your point of having only one item remained at last :) Thanks – Suraj Malviya Mar 22 '16 at 19:56
  • but on putting the code `if(model.getSize()!=0) { model.removeAllElements(); }` just before the `for` loop and inside the `if(!searchText.isEmpty())` i am facing the same exception – Suraj Malviya Mar 22 '16 at 20:03
  • @surajmalviya, There is no need for the if condition. You just always remove the items from the comb box, before you start your search loop. I didn't say this would stop the Exception. I suggested you need a SwingUtilities.invokeLater(...) to stop the Exception. Please take the time to read the suggestions. – camickr Mar 22 '16 at 20:09