We help IT Professionals succeed at work.

Unique Selections in ComboBoxes - part 2

jkteater
jkteater asked
on
Medium Priority
346 Views
Last Modified: 2012-05-12
now that we have all three boxes where you can not have the same user name in any of the boxes at the same time.  That works great!

The problem is what happens if the user changes their mind and selects a different user.  

Example:

KeyUser = jkteater <- is selected and removed from the list so that AME and PME can not have the jkteater value to select
AME =
PME =

What if the user selects jkteater and then figures out that is the wrong keyuser and selects jsmith.  Now jkeater is removed from the list and still can not be selected as a AME or PME


any ideas on how to address this?
Comment
Watch Question

Awarded 2011
Awarded 2011

Commented:
It is abslutely the same operation - in the item listner youu analyze what user selected - and adjust models if the other boxes so that they ave all neceesary choices -either by deleting or by adding some itens

Author

Commented:
I am not sure how we can add the name back since we have deleted the name and a new name has been selected
Awarded 2011
Awarded 2011

Commented:
How you were adding them in the first place?
Now make a method snalogous to the method you made for remove aand add to the same namse2Ids map the name which you need to reinstate

Author

Commented:
It is basically adding them from a list when the combo box is created.

So using the listener we just removed the selected name from the list.  

I am still a little confused on how I would get the name back once a new name is selected.
Awarded 2011
Awarded 2011

Commented:
Hard to understand where is your problem.
In the same itemStateChanged() method you can put as sophisticated logic as you want - nce you discover that this name is no longer sleceted you add it back
to the map which is underlying the model for other boxes. You understood that you can remove it - why can't you add it ?
You may need to add another m method to myModel class as you added it for removing - now add method for adding.
Only make sure you re modifing the same instance of the model - nit the new ine which you
just created as you did initially with removal part

Author

Commented:
You understood that you can remove it - why can't you add it ?

When I remove it, I am getting the selected value from the user

Object s =  keyUserComboBox.getSelectedItem();

so s is the value I am sending to my remove

keyUserModel.removeFromList(s);

so lets say they select jkteater

s = jkteater
keyUserModel.removeFromList(jkteater);

now jkteater has been removed from the list.  
So the user figures out that jkteater is the wrong keyuser and selects jsmith

so now s =  jsmith
keyUserModel.removeFromList(jsmith);

so I need to add jkteater back to the list

keyUserModel.addToList(??);  <-  I don't have jkteater stored anywhere to add it back.  S is now jsmith

I dont have a problem with the logic of adding it back to the list - I just don't understand how I can get the value of jkteater back after jsmith has been selected as the new keyuser


Awarded 2011
Awarded 2011

Commented:
You got all these loines in the first place from somwhere - from arary or sopmething - get frtom the same array -o you just need to be clearof your business logic
Awarded 2011
Awarded 2011

Commented:
Just cleary define - you get into oitemstatechjanged becoause the state of your boxes chnaged - now cjhecl all of them - discover those which are at this moment selected and again repopulate you models so that other boxes do not copmntain the one sleceted on other boxes - jkust first make sure that you are clear on what you want and these all things are doable
Awarded 2011
Awarded 2011

Commented:

when you are doing this in the first place:
  keyUserModel = new MyListModel(info.keyUserIds);
you get this list from this info object.
If the same info is available to you later in itemStateChanged() method
use it as a source of the names; if not make sure that when
you populate myModel first time, cerete additional ArrayList in
this myModel class which will be populated at this time and will
stay the same no matter how you moify that another collection which
directly determine contents of the combobox.

So when you arrive in itemStateListener() - you check waht item the user just slected and
repopulate your lits for the other two boxes so that it contains all items but the one
which user just selected on te first box - this is of course just one variant of possible strategies
or say when they sleect first box - you adjust list of the second box only
and when sthey sl;ecte  second box - you adjust list of the third based on first and seckond -
- all those different startegies, and the startegy is the part which should be considered carefully and slected
the one appropriate for your business need - you anyway should have the ability
to return to your original list and compare it with the selected utems and re-populate
some of the boxes accordingly.


 

Author

Commented:
See if this is way off

 public void itemStateChanged(ItemEvent ie) {
   if(ie.getSource().equals(keyUserComboBox)){
  Object s =  keyUserComboBox.getSelectedItem(); <== Getting the user input
 amePmeModel = amePmeRecoverModel;                <== Creating a copy of the model before any changes
   amePmeAltModel = amePmeAltRecoverModel;       <== Creating a copy of the model before any changes
   boolean blnFound = infoList.amePmeIds.contains(s); <== seeing the the input is in the list
   if (blnFound == true){                                             <== If the input is in the list then remove it
   amePmeModel.removeFromList(s);                          
   amePmeAltModel.removeFromList(s);
   }
   else {                                          <== if the info is not there it has been removed so use the copy models
      amePmeRecoverModel.removeFromList(s);  
      amePmeAltRecoverModel.removeFromList(s);
   }
 }

Author

Commented:
or should not put the logic in the itemState and add it to the remove method? and make a copy of the list instead of a model?
Awarded 2011
Awarded 2011

Commented:
no - defuiinitely no logic into remove method

 amePmeModel = amePmeRecoverModel;  - this is not creating a copy of the model

and you don't need any copies of any models

what is under it - a vector , an array, a hasmap - that should be copied - and copopied
explicitly - not just assuigned to another pointer - but one by one element
and that studff dshoudl always be kept - like your initial data


as i said in the beginning - you do not need any models
combobox with the constructor which takes vector - that is what you want
and keep a copy of yor oriigila list on one vector,
and then create those daghter vectors which will server as underklying vectors of your comboboxes
for every combobox
all copying ovf vectors better ro do element by element 0 then it is at least obvious wnhwt you are doing

Author

Commented:
Once again this will be a learning experience for me, I am afraid.  Please remember I was not the one that created this class.  I was asked to make sure each of the selections would be unique.

Here is the way I think things are working in the code

when the dialog is created they are creating a instance of a MyListModel

keyUserModel = new MyListModel(info.keyUserIds);

Open in new window

 <- info.keyUserIds is a list of shortnames from a different class

so they are sending in the list of shortnames to the class MyListModel
then in MyListModel they are putting the shortnames into a treemap

 
names2Ids = new TreeMap();
         for (int i = 0; i < loginIds.size(); ++i) {
            String id = (String) loginIds.get(i);
            names2Ids.put(id2Name(id), id);
         }

Open in new window


the names2Ids method is creating a stringbuffer and then going to a seperate class and getting the display name

public String id2Name(String id) {
         StringBuffer sb = new StringBuffer();
         Login l = EdiSystemData.getLoginFromId(id);
         if (l != null) {
            sb.append(l.getDisplayName());
            sb.append(" (" + id + ")");
         }
         else {
            sb.append(id);
         }
         return sb.toString();
      } // 

Open in new window


so now we have a list names2Ids that is formatted : John Teater (jkteater)

keyUserModel = new MyListModel(info.keyUserIds);

Open in new window

 so when that is created the list is added to the combo box

They made a model for each combo box

keyUserModel = new MyListModel(info.keyUserIds);
amePmeModel = new MyListModel(info.amePmeIds);
amePmeAltModel = new MyListModel(info.amePmeIds);

Open in new window


So I created a listener that when I a selection was made it would remove the name from the list in the model

 Object s =  keyUserComboBox.getSelectedItem();
	   	   amePmeModel.removeFromList(s);

Open in new window


In order to make the same changes in the other combo boxes I had to remove it from the other models

amePmeAltModel.removeFromList(s);

Open in new window


so when you are talking about combo boxes and vectors, I am a little confused.  I don't know if the way the code was written is the best way to do it, but it was what was given to me.

I would like to make a copy of the list names2Ids before any changes was made to it.  Being it is in the MyListModel class, can I just pass it to the class with the listener and make a copy of it there?

So About all the reading, but I am just trying to get my bearings
Awarded 2011
Awarded 2011

Commented:

>can I just pass it to the class with the listener and make a copy of it there

you can pass it to the method which handles your event, but kit is not logical - as
this is some prelimiary operation - to store a copy of it which would work for you all the time -
you don't want to make a copy every time I clicke on your combobox

You want to make a copy in the cosnstruyctor of MyListModel.
Still it may happen that you'll be doing it three times - when you crete instances
of MyListModel for each cmbobox - but this is not a very big deal
(you can avoid it by making this copy ststic and checking if it os already created,
but I'd not worry of such details- you probably do not have thousants of anmes there).

Author

Commented:
made a copy of the tree map in the constructor

I am going to make a method in my list model to check if the selected name is in the treemap

public void inList(Object s) {
    	  boolean blnFound = names2Ids.containsKey(s);
    	  if (blnFound == true){
    		  removeFromList(s);
    	  }
    	  else {
                  removeFromCopy(s);
          }     
 }


public void removeFromList(Object s) {
    	      names2Ids.remove(s);  
    	
      }

public void removeFromCopy(Object s) {
    	      copyTree.remove(s);  
    	
      }

Open in new window


So how do I set which list to be read in to the combo box?  All I have done above it to remove the user from the list - if the user is found in the list then remove them, if the user is not, then use the copy list and remove them there.  But I am not sure how to display the right list

Author

Commented:
I may have it - testing
Awarded 2011
Awarded 2011

Commented:
But I'd suggest to have a static copy - whic you would not change depedniong on the
user slecetion and which you can use for comparison in order to re-instate those which you deleted before;
maybe you are doing it like that but your methods removeFromCopy are not very obvious

Author

Commented:
Here is how I have it - and it dont seem to be working :(

 private TreeMap copyTree;

Constructor
names2Ids = new TreeMap();
         for (int i = 0; i < loginIds.size(); ++i) {
            String id = (String) loginIds.get(i);
            names2Ids.put(id2Name(id), id);
         }
copyTree = new TreeMap();
         for (int i = 0; i < loginIds.size(); ++i) {
            String id = (String) loginIds.get(i);
            names2Ids.put(id2Name(id), id);
         } 

Open in new window



 public void inList(Object s) {
          boolean blnFound = names2Ids.containsKey(s);
          if (blnFound == true){
              System.out.println("True\n");
        	  removeFromList(s);
          }
          else {
        	  System.out.println("False\n");    
        	  removeFromCopy(s);
          }     
     }
      
      public void removeFromList(Object s) {
    	    System.out.println("Remove from List " + s + "\n");
    	    names2Ids.remove(s);  
      }
      
      public void removeFromCopy(Object s) {
     	  System.out.println("Remove from Copy " + s + "\n");
    	  names2Ids = copyTree;
    	  names2Ids.remove(s);  
       }
       

Open in new window


Author

Commented:
the logic is not right at all

Author

Commented:
IF they select jkteater and then change it to jsmith - how would the code know that there was a change.  I am about back to the start - but I do have a copy of the Treemap
Awarded 2011
Awarded 2011

Commented:
cannot understand your code

create names2Ids1 in parallel with names2Ids and populate in the beginning
exactly in parallel with names2Ids
but then when you remove remove only from names2Ids and leave names2Ids1 unchanged

Author

Commented:
names2Ids = new TreeMap();
         for (int i = 0; i < loginIds.size(); ++i) {
            String id = (String) loginIds.get(i);
            names2Ids.put(id2Name(id), id);
         }
         
         names2Ids1 = new TreeMap();
         for (int i = 0; i < loginIds.size(); ++i) {
            String id = (String) loginIds.get(i);
            names2Ids1.put(id2Name(id), id);
         }

Open in new window


These two treemaps are the same - They are both created in the constructor

this is the remove when the name is first selected

public void removeFromList(Object s) {
    	      names2Ids.remove(s);  
      }

Open in new window




 if(ie.getSource().equals(keyUserComboBox)){
	   	   Object s =  keyUserComboBox.getSelectedItem();  <-- User A
	   	   amePmeModel.removeFromList(s);
}

Open in new window


So right now we have taken the selected input (User A)  from the user and removed it from  names2Ids
The user then decides to change the input from User A to User B.

I think right now we need to populate the combo boxes with the  names2Ids1 and remove User B from that list

I have no idea how the code will reconginze that User A has been changed to User B

Author

Commented:
I thought by doing this in the removeFromCopy method

 public void removeFromCopy(Object s) {
             names2Ids = names2Ids1;
            names2Ids.remove(s);  
       }

It would take the good copy names2Ids1 and assign it to names2Ids - so now names2Ids is a complete list and nothing has been removed. then we remove  names2Ids.remove(s);  User B

Author

Commented:
What if you created the models in the constructor and then when you enter a selection in the combo box it just some how reset the model back to new?  

if(ie.getSource().equals(keyUserComboBox)){
amePmeModel = new MyListModel(info.amePmeIds);
 Object s =  keyUserComboBox.getSelectedItem();
amePmeModel.inList(s);
}

or is that bad?

Author

Commented:
Never mind the last one - it was in correct in thought
Awarded 2011
Awarded 2011

Commented:

and never touch names2Ids1 - you should only read from it - to get idae of yourt total ist of strings

all modifications do in names2Ids
and you nesven need to assign one to the other - that may only confuse
Awarded 2011
Awarded 2011

Commented:
and never touch names2Ids1 - you should only read from it after you crated it in constryctor

Author

Commented:
what about storing the previous object that was selected and then having a function that adds it back in to the tree when the listener runs - check it for null, to make sure there is value there?

Awarded 2011
Awarded 2011

Commented:
Taht is also possible - I wanted to have acopy of everything
and comapre with the original ist every time and have a startegy - say
if I see this and thuis in comboboxes one and two, thaen dont want to se tese two
but want everyrthing else uin the third box

with the copy of everything and such (or antother but reasoanbley logical) startegy - you
can come upe with kone procedure which will oolook at those slected and figuer out the
list ofr all comboboxes which you need to have at this moment

If store tthose which you edeleted - then someties afdd them - you proably need to track from which box you removed them etc.
So that would be logically in my mind not soe clean
But agaiun i don't know your busines strategy
and hoe many times users can change thoers minds etc.
So you understadn that part and hopefully realisehow to implements all these situations - do
the way your busiess strategy can be formulated most logically
 

Author

Commented:
I do think the copy is the cleanest way to do what is needed, but I can not figure out the logic and how to compare the two list.  I would be glad to continue this way if you can help me with some of the logic and code
Awarded 2011
Awarded 2011

Commented:
You can every time in your event handler populate the name2id map from name2id1 just checkimg and skipping thoise items which are currently selected on other two boxes. Just itreate throurgh the noon-changing list and populate the name2id list element by eLement

Author

Commented:
so doing it that way I would not even need a remove method? So I would have a method in MyListModel

compareList(object s) {

iterate through name2id1
if (iterate.next != s){
 name2id.add(interate.next)
}

Something like that?

Then in the itemChange

Object s =  keyUserComboBox.getSelectedItem();
amePmeModel.compareList();


Would compareList need to return name2id or does it matter?
Awarded 2011
Awarded 2011

Commented:
yes, you would not need remove method or add method - you'll make the list every time frm scracth depednfding on what is shown on other comboboxes
thename compareLists is not very correct either
Make sure that you workk with exactly those isnatnces oof model which define the combobox not the newly created

Author

Commented:
how do I get the list of keys and not the values in the treemap

 Collection c = names2Ids1.values();
            Iterator itr = c.iterator();
            while (itr.hasNext()) {
               System.out.print(itr.next());
          }  

This is printing out the values, but I need the keys

Author

Commented:
I thin it is ketSet()
Awarded 2011
Awarded 2011

Commented:
You iterate through
 map.keySet() and retrive the vlaue for each key

This is more or less how you iterate through constant map (map)
and populate varying map (map1) with
all entries with the exception of some s1 and s2

for(String s : map.keySet()){
if(!s.equals(s1) && !s.equals(s2)){
String vlaue = map.get(s);
map1.put(s, vlaue);

}

}

Author

Commented:
here is what I have

public void compareList(Object s){
    	  
    	  for(Object s3 : names2Ids1.keySet()){
    		  if(!s3.equals(s)){
    		  Object value = names2Ids1.get(s);
    		  names2Ids.put(s, value);
    		  }
    	  }
     
      }

Open in new window


Then in the ActionItem

 public void itemStateChanged(ItemEvent ie) {
	 if(ie.getSource().equals(keyUserComboBox)){
	   	  Object s =  keyUserComboBox.getSelectedItem();
	   	  amePmeModel.compareList(s);
	     	   	 
	 }

Open in new window


So with the following code I am thinking that the combo box in amePmeModel should show the new list with out the selection from keyUserComboBox

but it still shows the complete list

Author

Commented:
I know that the logic is working in the if statment
Awarded 2011
Awarded 2011

Commented:

 public void itemStateChanged(ItemEvent ie) {
       if(ie.getSource().equals(keyUserComboBox)){
                 Object s =  keyUserComboBox.getSelectedItem();
                 amePmeModel.compareList(s);
                  your_comobx_name.setModel(amePmeModel);           // add this statement
       }

Author

Commented:
That did not make a difference :(  - does compareList need to return the MAP?
It just don't seem like the amepme combo box is getting the updated map

Author

Commented:
increasing the points
Awarded 2011
Awarded 2011

Commented:
public void compareList(Object s){
    	   names2Ids = new TreeMap(); // add this line
    	  for(Object s3 : names2Ids1.keySet()){
    		  if(!s3.equals(s)){
    		  Object value = names2Ids1.get(s);
    		  names2Ids.put(s, value);
    		  }
                  
    	  }
your_comobx_name.setModel(amePmeModel);           
     
      }

Open in new window

Awarded 2011
Awarded 2011

Commented:
No pints can measure this kind of effort, as you can probably imagine.
Awarded 2011
Awarded 2011

Commented:
I of course meant to say:

No points can measure this kind of effort, as you can probably imagine :)

Author

Commented:
Ok this seems strange - but for the fun of it I added

public void compareList(Object s){
    	  
    	  for(Object s3 : names2Ids1.keySet()){
    		  if(!s3.equals(s)){
    			  Object value = names2Ids1.get(s3);
    			  names2Ids.put(s3, value);
    			
    		  }
    	  }
    	  names2Ids.remove(s);
      }

Open in new window


and it seems to be working
Awarded 2011
Awarded 2011

Commented:
No, that's not the way you want - you alredy did that for removing, but you need to recreate it alltogether for all cases.
Add creating new treeMap - otherwise you'll not see it changing as you are adding to the old map and only ovrwriting some - you need to create blank treempa before

Author

Commented:
Yes with more testing you are correct - it does not work.


No pints can measure this kind of effort, as you can probably imagine.

I thought a couple of pints sounded pretty good about right now!!!
Awarded 2011
Awarded 2011

Commented:
No, it should work - did you add re-creating the TreeMap
It is just when you adding you perveious stuff does not  go away.
If you crete new treeMap and add only those which you need - it should not have those whicvh you do not need

Author

Commented:
Let me make sure I understand something.

keyUserModel = new MyListModel(info.keyUserIds);  - we are creating a instance of a model (keyUserModel)
keyUserComboBox = new JComboBox(keyUserModel); - we are creating a combo box in that instance of the model

Object s =  keyUserComboBox.getSelectedItem(); - we are getting a value from the keyUserComboBox
amePmeModel.compareList(s); - we are running the method in the instance of the model (amePmeModel ) so what ever compareList does it only pertains to the model (amePmeModel ).  That is why we have to do amePmeAltModel.compareList(s); as well - to make ssure the changes are in model(amePmeAltModel) as well.

So when the dialog is first created
amePmeComboBox is being populated by the default list with no changes.

when the user selects a KeyUser we want to take a copy of the default list and interate through it looking for the selected object.  If there is not a match we rewrite the default list without the selected object

so in a perfect world the amePmeComboBox is now populated with a revised default list.

when I run the compareList method as is - I do not see any changes to the  amePmeComboBox list
but when I add remove(s) to the bottom of the method - The changes so up.  I know that is not the right way to do it.  I just wonder why it shows up then
Awarded 2011
Awarded 2011

Commented:
did you add creatinon of TreeMap as I showed in the last post ?

Author

Commented:
public void itemStateChanged(ItemEvent ie) {
	 if(ie.getSource().equals(keyUserComboBox)){
	   	  Object s =  keyUserComboBox.getSelectedItem();
	   	  amePmeModel.compareList(s);
	   	  amePmeAltModel.compareList(s);
	 }

Open in new window



public void compareList(Object s){
    	  
    	  for(Object s3 : names2Ids1.keySet()){
    		  if(!s3.equals(s)){
    			  Object value = names2Ids1.get(s3);
    			  names2Ids.put(s3, value);
    		  }
    	  }
    	  
      }

Open in new window


Here is what I have right now

Author

Commented:
I am assuming you are referring to compareList as recreating the tree
Awarded 2011
Awarded 2011

Commented:
public void compareList(Object s){
    	   names2Ids = new TreeMap(); // add this line - that is what I'm writing abot see 37078337
    	  for(Object s3 : names2Ids1.keySet()){
    		  if(!s3.equals(s)){
    		  Object value = names2Ids1.get(s);
    		  names2Ids.put(s, value);
    		  }
                  
    	  }
your_comobx_name.setModel(amePmeModel);           
     
      }

Open in new window

Author

Commented:
public void compareList(Object s){
    	  names2Ids = new TreeMap();
    	  for(Object s3 : names2Ids1.keySet()){
    		  if(!s3.equals(s)){
    			  Object value = names2Ids1.get(s3);
    			  names2Ids.put(s3, value);
    		  }
    	  }
    	
      }

Open in new window


I did add this and it seems like 2 of the 3 boxes are working correctly

KeyUser works
AME works
PME does not show what is in AME but does show what is in KeyUSer

Author

Commented:
I think it is becuase we are only looking for one object and not 2 - you did have that in your eariler code

if(!s.equals(s1) && !s.equals(s2)){

I pass in s1 from user input but not sure how to get s2 to pass in
Awarded 2011
Awarded 2011

Commented:
well, this is tricky in a sense that when you run this method
it will remove this particular value but will add everything else;
so if you say run it twice with different parameter only the last one will not be prsent - you should
feed both (or ArrayList containig these both) and skipp both if you want not to see both of them
Awarded 2011
Awarded 2011

Commented:
if you have thre boxes and you don't want to see in the third selected any of the two others, then
your method has to have two parameters - so you first determine the vlues in two remaining boxes and feed bothe of thwem
as arguments to the method and then check as i showed beofore.

For the general case of number of boxes you'll want to feed the array list as argument

Author

Commented:
I don't know how you can do that- We can't feed both because it pretty much a single selection.  I am not sure how you would use a Arraylist because there should never be more that 2 objects in the ArrayList, so it has to be smart enough to know when to older selections
Awarded 2011
Awarded 2011

Commented:
>because it pretty much a single selection

I'm talking about two boxes - so each one has one selection, but if you want to remove both of them, then you should remove two

Author

Commented:
I know that you know all about this issue and know ever part of it.  I don't mean to be repeating myself, but it is about the only way I can understand what I am doing

3 boxes

KeyUser
AME
PME

when a object is selected in KeyUser - it needs to not be avavialbe for AME AND PME
when a object is selected in AME as well - both objects should not be avaible for PME

All three boxes should work the same - If I have to I can only enable a box once once the box above has a value

KeyUser enable
AME not
PME not

KeyUser = selection
AME enabled
PME not

If you think that would help?

I do not know how to get the 2 object selections. even using a arraylist - I dont get how you can do that when you the listener is acting off a single selection.


These is my action method

 public void itemStateChanged(ItemEvent ie) {
	 if(ie.getSource().equals(keyUserComboBox)){
	   	  Object s =  keyUserComboBox.getSelectedItem();
	   	  amePmeModel.compareList(s);
	   	  amePmeAltModel.compareList(s);
	 }
	 if(ie.getSource().equals(amePmeComboBox)){
	   	   Object s =  amePmeComboBox.getSelectedItem();
	   	   keyUserModel.compareList(s);
	   	   amePmeAltModel.compareList(s);
	   	   
	 }
	 if(ie.getSource().equals(amePmeAltComboBox)){
	   	   Object s =  amePmeAltComboBox.getSelectedItem();
	   	   keyUserModel.compareList(s);
	   	   amePmeModel.compareList(s);
	 }
  }

Open in new window


If the user selects the keyuser, we can not wait to get another selection for ame to send the compareList.  Once keyuser is selected it needs to be removed from AME before they select anything

Author

Commented:
Do you create a method to add the selections to a arraylist and then somehow make sure that the arraylist is only holding the last 2 selections and then use the arraylist in the compareList?
Awarded 2011
Awarded 2011

Commented:
Understand that listener is only triggering an event
you can at any momemnt in your code read the current selection from any box - and this has nothing to do with any listener

>when a object is selected in AME as well - both objects should not be avaible for PME

so at the moment when when  a user slecets in AME - that triggers event - and starts your event handler
method.

In thhis method you don't nececcarrily need to read ONLY ONE BOX, you CAN read what is currently seleceted in BOTH boxes
(no mmatter that event was tiggerred by the act of selection only in the second box)

And then you send both of thiose which you read fromtwo previous boxes
as parameters to your method - and make sure that neither of them is included in the ,ist
for the third box

Author

Commented:
I see
Awarded 2011
Awarded 2011

Commented:
	 if(ie.getSource().equals(amePmeComboBox)){
	   	   Object s =  amePmeComboBox.getSelectedItem();
   Object s2 =  keyUserComboBox.getSelectedItem();
	   	   keyUserModel.compareList(s, null); // don't know what is your policy ofr this list in this case
	   	   amePmeAltModel.compareList(s, s2); // but here you need to remove both  and of course you need to modify method to take two arguiemnts
	   	   
	 }
  }

Open in new window

Author

Commented:
public void itemStateChanged(ItemEvent ie) {
	 if(ie.getSource().equals(keyUserComboBox)){
	   	  Object s =  keyUserComboBox.getSelectedItem();
	   	  Object s2 = amePmeComboBox.getSelectedItem();
	   	  amePmeModel.compareList(s, null);
	   	  amePmeAltModel.compareList(s, s2);
	 }
	 if(ie.getSource().equals(amePmeComboBox)){
	   	   Object s =  amePmeComboBox.getSelectedItem();
	   	   Object s2 = keyUserComboBox.getSelectedItem();
	   	   keyUserModel.compareList(s, null);
	   	   amePmeAltModel.compareList(s, s2);
	   	   
	 }
	 if(ie.getSource().equals(amePmeAltComboBox)){
	   	   Object s =  amePmeAltComboBox.getSelectedItem();
	       Object s2 = amePmeComboBox.getSelectedItem();
	   	   keyUserModel.compareList(s, null);
	   	   amePmeModel.compareList(s, s2);
	 }
  }

Open in new window


Does that look right?

Author

Commented:
It is almost like I need to check all three?

Author

Commented:
I am still getting

Keyuser = A

A is not avaible in the other 2 AME and PME

KeyUser = A
AME = B
now PME does not have B but has A
Awarded 2011
Awarded 2011

Commented:
More or less - but you should have clear in your mind all cases - i juts wrote this
amePmeModel.compareList(s, null);
because I didn't know.
So this would allow in AME box to have the same as in PME box, but not as in keyUser box - maybe
you want to check both other boxes and don't allow it in third box in all cases what is in at least one
of the boxes  - just think what you need
and act accordingly
Awarded 2011
Awarded 2011

Commented:
KeyUser = A
AME = B
now PME does not have B but has A

how can this happen if you removed both of them in this method
amePmeModel.compareList(s, s2);
check that you did everything right

Author

Commented:
Yes there was a problem with my IF statement - I have fixed that but now I figure out this last box

if(ie.getSource().equals(amePmeAltComboBox)){
                   Object s =  amePmeAltComboBox.getSelectedItem();
               Object s2 = amePmeComboBox.getSelectedItem();
                   keyUserModel.compareList(s, null);
                   amePmeModel.compareList(s, s2);
         }
  }

I dont think that is right - it is exact copy of the the second box, so when I select something in the 3rd box it removes the selection in the second box
Awarded 2011
Awarded 2011

Commented:
but it is all in your hands - if you don't want it to happen - remove one of the calls to recreate the list - just think waht you need and act correspiondingly

Author

Commented:
I think I am going to go have a pint and readdress this in the morning.  Here is what I tried - LOL - does not work

public void itemStateChanged(ItemEvent ie) {
	 if(ie.getSource().equals(keyUserComboBox)){
	   	  Object s =  keyUserComboBox.getSelectedItem();
	   	  Object s2 = amePmeComboBox.getSelectedItem();
	   	  Object s3 = amePmeAltComboBox.getSelectedItem();
	   	  if (s2 == null && s3 == null) {
	   		amePmeModel.compareList(s, null, null);
	   		amePmeAltModel.compareList(s, null, null);
	   	  }
	   	  else if (s2 != null && s3 == null){
	   		amePmeModel.compareList(s, s2, null);
		   	amePmeAltModel.compareList(s, s2, null); 
	   	  }
	   	  else {
	   		amePmeModel.compareList(s, s2, s3);
		   	amePmeAltModel.compareList(s, s2, s3);
	   	  }
	 }
	 if(ie.getSource().equals(amePmeComboBox)){
	   	   Object s =  amePmeComboBox.getSelectedItem();
	   	   Object s2 = keyUserComboBox.getSelectedItem();
	   	   Object s3 = amePmeAltComboBox.getSelectedItem();
	   	   if (s2 == null && s3 == null) {
	   		keyUserModel.compareList(s, null, null);
	   		amePmeAltModel.compareList(s, null, null);
	   	   }
	   	   else if (s2 != null && s3 == null){
	   		keyUserModel.compareList(s, s2, null);
		   	amePmeAltModel.compareList(s, s2, null); 
	   	   }
	   	   else {
	   		keyUserModel.compareList(s, s2, s3);
		   	amePmeAltModel.compareList(s, s2, s3);
	   	   }
	   	   
	 }
	 if(ie.getSource().equals(amePmeAltComboBox)){
	   	   Object s = amePmeAltComboBox.getSelectedItem();
	       Object s2 = keyUserComboBox.getSelectedItem();
	       Object s3 = amePmeComboBox.getSelectedItem();
	       if (s2 == null && s3 == null) {
		      keyUserModel.compareList(s, null, null);
		   	  amePmeModel.compareList(s, null, null);
		   }
		   else if (s2 != null && s3 == null){
		      keyUserModel.compareList(s, s2, null);
			  amePmeModel.compareList(s, s2, null); 
		   }
		   else {
		      keyUserModel.compareList(s, s2, s3);
			  amePmeModel.compareList(s, s2, s3);
		   }
	 }
  }

Open in new window

Awarded 2011
Awarded 2011

Commented:
Before doing anything - sit doewn and write for yourself - what you want, like
if the firs box has selction A then A should not be present in both secnond and thiord
if the frst box has A and second B then the thir should not have eother A or B
etc.

write this all and then implement it

Untill you dnont understand what you want you'll never do it right
All that has nothing to do with how to do it - you saw how it works
It has only to do with understanding exactly your
business logic
Awarded 2011
Awarded 2011
Commented:
OK, this is a simple program with three comboboxes
and neither will allow you to select
any of the names which are shown in one of the other two boxes.

Compile it, study it and make sure you understand
100% how event handlers work here.
Of course it would be much eaiser not to have any
combobox models but jsut have simple vector of strings
underlying each box, but I made these models
to make it the way it is done in your
program. After all, it does not matter
in the way it treats the events and modifies model - the logic is the same.

Study this program, ask questions about it - if you don;t understand something and
I hope you'll have no questions about this business any more.

What is the logic - do you want it to be as excclusive as in this case -
- none of the boxes allow any of the values in other two boxes or less restrictive - that depends
on your busines requirements. Understand those - and make accordingly - it is all in your hands.



import javax.swing.*;
import javax.swing.event.ListDataListener;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;

public class ThreeBoxes extends JFrame  implements ItemListener
{

    JComboBox one;
    JComboBox two;
    JComboBox three;

    static ArrayList <String> allNames;



    public ThreeBoxes() {



   ArrayList <String> ar = new ArrayList<String>();

        ar.add("Mike");
        ar.add("Pete");
        ar.add("Alex");
        ar.add("Jane");
        ar.add("Kate");
        ar.add("Mary");
     allNames = new ArrayList<String>();   
     allNames.addAll(ar);


     MyListModel m1 = new MyListModel(ar);
      one = new JComboBox();
        one.setModel(m1);

         MyListModel m2 = new MyListModel(ar);
      two = new JComboBox();
        two.setModel(m2);

            MyListModel m3 = new MyListModel(ar);
      three = new JComboBox();
        three.setModel(m3);

        one.addItemListener(this);
             two.addItemListener(this);
             three.addItemListener(this);

        Container c = this.getContentPane();
        c.setLayout(new FlowLayout());
        c.add(one);
        c.add(two);
        c.add(three);
        this.setSize(300,300);
        this.setVisible(true);


    }


 public void itemStateChanged(ItemEvent ie){
      Object s1 = one.getSelectedItem();
         Object s2 = two.getSelectedItem();
           Object s3 = three.getSelectedItem();
      MyListModel mm1 = (MyListModel) one.getModel();
      MyListModel mm2 = (MyListModel) two.getModel();
      MyListModel mm3 = (MyListModel) three.getModel();

     if(ie.getSource().equals(one)) {


         mm2.recreateList(s1,s3);
         two.setModel(mm2);

         mm3.recreateList(s1,s2);
         three.setModel(mm3);
     }
     if(ie.getSource().equals(two)) {
         mm1.recreateList(s2,s3);
           one.setModel(mm1);
                 mm3.recreateList(s2,s1);
           three.setModel(mm3);

     }
     if(ie.getSource().equals(three)) {
         mm1.recreateList(s2,s3);
           one.setModel(mm1);
                 mm2.recreateList(s3,s1);
           two.setModel(mm2);

     }





 }

    public static void main(String[] args) {
        new ThreeBoxes();
}

}

class MyListModel extends AbstractListModel implements ComboBoxModel {
    ArrayList<String> ar;
    String selection = null;

    public MyListModel(ArrayList<String> ar){
        this.ar = ar;
    }
    public Object getSelectedItem() {
          return selection;
    }
    public void setSelectedItem(Object o){
         selection = (String) o;
    }

    public int getSize(){
        return ar.size();
    }
  public void removeListDataListener(ListDataListener li){}

  public Object getElementAt(int i){
      return ar.get(i);
  }


     public void addListDataListener(ListDataListener li){}

    public ArrayList<String> getArrayList(){
        return ar;
    }

    public void setArrayList(ArrayList<String> ar){
        this.ar = ar;
    }

    public void recreateList(Object s1, Object s2) {
        ar = new ArrayList<String>();
        for(String s : ThreeBoxes.allNames){
            if(s.equals(s1) || s.equals(s2))continue;
            ar.add(s);
        }

    }

}

Open in new window



threeboxes.PNG

Author

Commented:
I took your code and studied it and it all started to make sense.  That was very nicely done and I am sorry it took you having to write code for me to understand the logic.   But I know if I have to write combo boxes I will use vectors and not models.

As Always thanks very much!!!!
Awarded 2011
Awarded 2011

Commented:
You are always welcome.
Glad, that this short program helped.

If you want a good exercise in the same vein when you have some spare time - make an application which would have one more box (4 boxes total; maybe you can also add two more names to the list) and would never allow to have predominance of male or female among selected names by more than one.

Explore More ContentExplore courses, solutions, and other research materials related to this topic.