Results 1 to 9 of 9

Thread: ComboBoxBinder: changes in one combobox changes another

Hybrid View

  1. #1
    Join Date
    Sep 2009
    Posts
    4

    Default ComboBoxBinder: changes in one combobox changes another

    Hi.

    I'm using the formbuilder to create a form. If the user selectes a value in one combobox, I want another combobox to alter it's content.

    What I want is that if the user chooses "item1" in the first combobox, the second combobox will allow the user to choose between
    "item1 - 1"
    "item1 - 2"

    If the user chooses "item2" in the first combobox, the second combobox will allow the user to choose between
    "item2 - 1"
    "item2 - 2"

    It seems that the changes are not reflected in the gui.

    This is my bean that is backing the form:

    Code:
    public class TestObject {
    	private String selectedInList1;
    	private String selectedInList2;
    	private List<String> list1;
    	private List<String> list2;
    	
    	private List<String> list2whenItem1Selected;
    	private List<String> list2whenItem2Selected;
    	 private ExtendedPropertyChangeSupport changeSupport = new ExtendedPropertyChangeSupport(
    			this);
    	
    	public TestObject() 
    	{
    		list1 = new ArrayList<String>();
    		list1.add("item1");
    		list1.add("item2");
    		
    		list2whenItem1Selected = new ArrayList<String>();
    		list2whenItem1Selected.add("item1 - 1");
    		list2whenItem1Selected.add("item1 - 2");
    		
    		list2whenItem2Selected = new ArrayList<String>();
    		list2whenItem2Selected.add("item2 - 1");
    		list2whenItem2Selected.add("item2 - 2");
    		
    		list2 = list2whenItem1Selected;
    		
    		selectedInList1 = list1.get(0);
    		selectedInList2 = list2.get(0);
    	}
    
    	public String getSelectedInList1() {
    		return selectedInList1;
    	}
    
    	public void setSelectedInList1(String selectedInList1) {
    		String old = this.selectedInList1;
    		this.selectedInList1 = selectedInList1;
    		if( "item1".equals(selectedInList1) ) {
    			setList2(list2whenItem1Selected);
    		} else {
    			setList2(list2whenItem2Selected);
    		}
    		setSelectedInList2(list2.get(0));		
    		changeSupport.firePropertyChange("selectedInList1", old, selectedInList1);
    		
    	}
    
    	public String getSelectedInList2() {
    		return selectedInList2;
    	}
    
    	public void setSelectedInList2(String selectedInList2) {
    		String old = this.selectedInList2;
    		this.selectedInList2 = selectedInList2;
    		changeSupport.firePropertyChange("selectedInList2", old, selectedInList2);
    	}
    
    	public List<String> getList1() {
    		return list1;
    	}
    
    	public void setList1(List<String> list1) {
    		List<String> old = this.list1;
    		this.list1 = list1;
    		changeSupport.firePropertyChange("list1", old, list1);
    	}
    
    	public List<String> getList2() {
    		return list2;
    	}
    
    	public void setList2(List<String> list2) {
    		List<String> old = this.list2;
    		this.list2 = list2;
    		changeSupport.firePropertyChange("list2", old, list2);
    	}
    	
    	public void removePropertyChangeListener(PropertyChangeListener x) {
    		changeSupport.removePropertyChangeListener(x);
    	}
    	
    	public void addPropertyChangeListener(PropertyChangeListener x) {
    		changeSupport.addPropertyChangeListener(x);
    	}
    	
    	
    }
    Then I create the form like this:

    Code:
    public class TestForm extends AbstractForm {
    	public TestForm(final TestObject testObject) {
    		super(FormModelHelper.createFormModel(testObject, false, "testForm"));
    		testObject.addPropertyChangeListener(new PropertyChangeListener() {
    			
    			public void propertyChange(PropertyChangeEvent evt) {
    				getControl().repaint();
    				System.out.println("testObject list2: " + testObject.getList2() + " form:" + getFormModel().getValueModel("list2").getValue());
    				
    			}
    		});
    	}
    	
    	@Override
    	public JComponent createFormControl() {
    		TableFormBuilder builder = new TableFormBuilder(getBindingFactory() );
    		{
    			Map context = new HashMap();
    			context.put(ComboBoxBinder.SELECTABLE_ITEMS_KEY,getValueModel("list1"));
    			ComboBoxBinder comboBoxBinder = new ComboBoxBinder();
    			Binding binding = comboBoxBinder.bind(getFormModel(), "selectedInList1", context);
    			builder.add(binding);
    		}
    		
    		{
    			Map context = new HashMap();
    			context.put(ComboBoxBinder.SELECTABLE_ITEMS_KEY,getValueModel("list2"));
    			ComboBoxBinder comboBoxBinder = new ComboBoxBinder();
    			Binding binding = comboBoxBinder.bind(getFormModel(), "selectedInList2", context);
    			builder.add(binding);
    		}
    		return builder.getForm();
    	}
    
    }
    The output from the listner is:

    testObject list2: [item1 - 1, item1 - 2] form:[item1 - 1, item1 - 2]
    testObject list2: [item2 - 1, item2 - 2] form:[item2 - 1, item2 - 2]

    the second combox (that reflects list2) show
    "item1 - 1".

    When I resize the window, the text changes to
    "item2 - 1"

    But when I click on the second combobox my options are
    "item1 - 1" and "item1 - 2"

    I would expect it to be
    "item2 - 1" and "item2 - 2"

    Why doesn't it behave as I expect? Does anyone have any idea how I can achive my wanted behavior?

    Best Regards,
    .t

  2. #2
    Join Date
    Mar 2007
    Location
    Oudenaarde
    Posts
    294

    Default

    Hmmm...

    If I remember correctly, changing the list behind a combobox will indeed not show the changes. You need to change the internal model instead of the backing list. Also, you need to make sure you make those changes on the EDT.
    MSN: PM me please
    Skype: doclo_lieven

    Spring Rich Client Project Lead

  3. #3
    Join Date
    Sep 2009
    Posts
    4

    Default

    Quote Originally Posted by LievenDoclo View Post
    Hmmm...

    If I remember correctly, changing the list behind a combobox will indeed not show the changes. You need to change the internal model instead of the backing list. Also, you need to make sure you make those changes on the EDT.
    Thanks for the fast response. :-)

    What do you mean by internal model? The Valuemodel? (I'm sorry if I ask stupid questions, but I'm new to Spring RCP).

    It seems the valuemodel is changed when I change the backing bean. The listener set up in forms constructor:

    Code:
    System.out.println("testObject list2: " + testObject.getList2() + " form:" + getFormModel().getValueModel("list2").getValue());
    will print

    testObject list2: [item2 - 1, item2 - 2] form:[item2 - 1, item2 - 2]

    which indicates that the valuemodel in the form contains the correct values.

  4. #4
    Join Date
    Mar 2007
    Location
    Oudenaarde
    Posts
    294

    Default

    No, the internal model of the combobox, the combobox model. In your backing bean, you're changing the backing list of the combobox. But Swing doesn't show changes in a backing list, only changes to the comboboxmodel are propagated iirc. I'll see if I can create a test case to mimic your case.
    What you could do is add a changelistener to the valuemodel of one of the comboboxes and change the selectable items list in there (I'm freewheeling here), perhaps that'll work, but I can't say for sure.
    MSN: PM me please
    Skype: doclo_lieven

    Spring Rich Client Project Lead

  5. #5
    Join Date
    Sep 2009
    Posts
    4

    Default

    Quote Originally Posted by LievenDoclo View Post
    No, the internal model of the combobox, the combobox model. In your backing bean, you're changing the backing list of the combobox. But Swing doesn't show changes in a backing list, only changes to the comboboxmodel are propagated iirc. I'll see if I can create a test case to mimic your case.
    What you could do is add a changelistener to the valuemodel of one of the comboboxes and change the selectable items list in there (I'm freewheeling here), perhaps that'll work, but I can't say for sure.
    Oki. I thought the point of using the form was that the backing bean was bound to the gui components so that changes to the gui are propagated to the backing bean and vice versa.

    I have figured out one way of doing it that actually works, but I find it's a lot of code for something that should be really easy. I replace the combobox model, listen to changes in the backing bean's property and update the combobox model accordingly.

    The changes to the selected value seems to work as I would expect - changes to the backing bean are propagated to the gui, without the need to explicitly change them. It is only the list of selectable items that are not propagated back to the gui. Seems a bit strange to me.

    Code:
    {
    			Map context = new HashMap();
    			context.put(ComboBoxBinder.SELECTABLE_ITEMS_KEY,getValueModel("list2"));
    			
    			Binding binding = comboBoxBinder.bind(getFormModel(), "selectedInList2", context);
    			
    			
    			final JComboBox comboBox = (JComboBox) builder.add(binding)[1];
    			TestObject testobject = (TestObject) getFormObject();	
    			comboBox.setModel(new DynamicComboBoxListModel(getValueModel("selectedInList2"), getValueModel("list2")));
    			testobject.addPropertyChangeListener(new PropertyChangeListener() {
    				
    				public void propertyChange(PropertyChangeEvent evt) {
    					if( "selectedInList1".equals(evt.getPropertyName())) {
    						DynamicComboBoxListModel comboBoxModel = (DynamicComboBoxListModel) comboBox.getModel();
    						comboBoxModel.replaceWith((Collection) getValueModel("list2").getValue());
    					}
    					
    				}
    			});
    			
    		}

  6. #6
    Join Date
    Mar 2007
    Location
    Oudenaarde
    Posts
    294

    Default

    If you look closely to your example, you've explained it yourself:

    Code:
    comboBoxBinder.bind(getFormModel(), "selectedInList2", context);
    You're binding the selected value, not the selectable values. At the moment, it's not yet possible to bind the selectable list, so your example does the trick quite nicely.
    MSN: PM me please
    Skype: doclo_lieven

    Spring Rich Client Project Lead

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •