Search code examples
javaswingjcomboboxitemlistener

Two JComboBoxes user can't choose same value


I've got two JComboBox. First one has model with elements "one", "two", "three" and second has model with elements "three", "four". And when user choose element "three" in first JComboBox, he can't choose element "three" in second one JComboBox. And in reverse - when user choose element "three" in second one JComboBox, he can't choose same element in first one CB. How can i do this in Java ?

Thank you for answers. One more question. When i dynamically create ComboBoxes (when someone clicked the button - in button actionListener), and every new ComboBox has same model - same list of elements. How can i check this case ? Same like Blip said ?


Solution

  • In my opinion you could add ItemListener to the 2 JComboBox. If the user selects the object "three" in any of the JComboBox then the object "three" could be removed from the other JComboBox's model. And if the user deselects the object "three" in one JComboBox then the object "three" can be added to the model of the other JComboBox.

    You could implement in the following way:

    1. Lets have have the two JComboBox stored in variables box1 and box2 which could be implemented as :

      JComboBox<String> box1 = new JComboBox<>(new String[]{"one", "two", "three"});
      JComboBox<String> box2 = new JComboBox<>(new String[]{"three", "four"});
      
    2. Now add itemListener to both these JComboBox and pass it to a method say boxItemSelected:

      box1.addItemListener(new ItemListener(){
      
          itemStateChanged(ItemEvent e){
              boxItemSelected(e);
          }
      });
      box2.addItemListener(new ItemListener(){
      
          itemStateChanged(ItemEvent e){
              boxItemSelected(e);
          }
      });
      
    3. Now to implement the boxItemSelected(e)

      void boxItemSelected(ItemEvent e){
      
          //Check the item selected/deselected is "three" else do nothing.
          if (e.getItem().equals("three")){ 
      
          //Find the box on which this action was not performed to change its model.
              JComboBox<String> oppositeBox;
              if(e.getSource().equals(box1)){
                  oppositeBox = box2;
              }else{
                  oppositeBox = box1;
              }
      
          //Check the item is selected or deselected to remove or add "three" to item list.
              if(e.getStateChange() == ItemEvent.SELECTED){
                  oppositeBox.removeItem("three");
              }else{
                  oppositeBox.addItem("three");
              }
          }
      }
      

    Addition Information

    Here if you have more than 1 items that are overlapping and can be selected only in one JComboBox, a slight modification of the method boxItemSelected could be take care of your problem as Illustrate below:

    Change the line in the above code from:

    if (e.getItem().equals("three"))
    

    to

    if (e.getItem().equals("three") || e.getItem().equals("<new item>") || ....)
    

    And change

    oppositeBox.removeItem("three");
    oppositeBox.addItem("three");
    

    to

    oppositeBox.removeItem(e.getItem());
    oppositeBox.addItem(e.getItem());
    

    Here under any circumstance the user cannot select the same items in both the JComboBox. And all these happen behind the scene without the knowledge of the user using the user-interface.

    When i dynamically create ComboBoxes (when someone clicked the button - in button actionListener), and every new ComboBox has same model - same list of elements. How can i check this case ? Same like Blip said ?

    In response to the above I am considering that all the items in all the JComboBox same and are stored in a List variable, and if 1 item is selected in any one of the JComboBox then that item cannot be selected in rest of the JComboBox. If my assumption is correct, then I suggest you do the following:

    1. Create a List<JComboBox<?>> say boxes and initialise it as below:

      List<JComboBox<?>> boxes = new ArrayList<>();
      
    2. In your JButton (the button that dynamically JComboBox) variable's ActionListener implementation create a variable say items as an instance of List to store the items of the JComboBox and add the items

      List<String> items = new Vector<>();
      items.add("One");
      items.add("Two");
      ......
      
    3. Now remove the items from from the items variable that are selected in other JComboBox that are dynamically generated:

         Iterator<JComboBox<?>> iterator = boxes.iterator();
         while(iterator.hasNext()){
             JComboBox<?> existing = iterator.next();
             items.remove(existing.getSelectedItem());
         }
      
    4. Now after initialisation of the JComboBox instance say box set the Model of the box to the previously initialised and trimmed List variable items

      box.setModel(new DefaultComboBoxModel(items));
      
    5. now add the JComboBox variable box to the List variable boxes:

      boxes.add(box);
      
    6. Also in this above mentioned ActionListener implementation add the ItemListener to box, the newly instantiated variable of JComboBox and pass it to the method boxItemSelected:

      box.addItemListener(new ItemListener(){
      
          itemStateChanged(ItemEvent e){
              boxItemSelected(e);
          }
      });
      
    7. Now the implementation of the boxItemSelected has to be changed to accommodate the changes:

      void boxItemSelected(ItemEvent e){
      
          //Create an iterator to iterate over the boxes 
          Iterator<JComboBox<?>> iterator = boxes.iterator();
      
          while(iterator.hasNext()){
      
              //Get the current instance of comboBox from the list
              JComboBox<?> current = iterator.next();
      
              //If the box in which the select or de-select 
              //event has occurred is the current comboBox then do nothing.
              if(e.getSource().equals(current)(
                  continue;
              }
      
              //If the event is select then remove the Item from the 
              //current comboBox else add the Item to the current comboBox.
              if(e.getStateChange() == ItemEvent.SELECTED){
                  current.removeItem(e.getItem());
              }else{
                  current.addItem(e.getItem());
              }
          }
      }