Forum Controls
Spotlight Features

The Rich Engineering Heritage Behind Dependency Injection

Andrew McVeigh takes us on a tour of the rich heritage behind dependency injection, what it represents, and tells us why its here to stay.

NetBeans 6: Matisse Updates

NetBeans 6 delivers great updates to the Matisse GUI builder. Spend a few minutes with Roman Strobl and get an expert briefing on what's new and what has changed.

Introduction to Groovy Part 3

In this, the third and final installation of Andres' Introduction to Groovy series, you learn about how Groovy handles variable numbers of arguments, named parameters, currying, and more about Groovy operators. Including, some new operators.

Easier Custom Components with Swing Fuse

Swing Fuse (actually just Fuse), is a framework designed to make it easier to create your own custom desktop components. In this article, Daniel Spiewak shows you how to get started and provides sample source code you can download.

Benchmark Analysis: Guice vs Spring

Willam Louth shows how he uses JXInsight Probes to investigate probable performance issues with code bases that he is not familiar with. He also highlights possible pitfalls in creating a benchmark, as well as in the analysis of results.
Replies: 6 - Pages: 1  
Threads: [ Previous | Next ]
  Click to reply to this thread Reply

JGoodies: Understanding Binding - Part 2

At 1:14 AM on Mar 10, 2005, R.J. Lorimer wrote:

Welcome back tip readers. I'm hoping all of you are ready to read more about the JGoodies binding framework. If you missed my last tip, too bad. Just kidding - you can find it here - JGoodies: Understanding Binding - Part 1 . Yesterday I briefly ran through the subject of JGoodies binding, with the hope I could show you enough to whet your appetite, but I didn't show a whole lot about the usage - I pretty much showed how to bind a text field and a checkbox, and that was it. There is so much more, however.

A Little More Detail

So you are feeling a lack of control because right now you can only use checkboxes and text fields? It seems to me it is surely possible to build an entire application out of just those. Surely you don't expect to be able to use sliders, radio buttons, lists and combo boxes - that'd just be greedy. While I suppose that would be an interesting study (building an application composed entirely of two component types), it doesn't sound very user friendly.

One of the things I always want to avoid with my tips is being to wordy. Let's face it - it's hard for me; I obviously can find more than enough to say about a subject, and manage to often do so incoherently on top of that. Thankfully, the binding framework speaks volumes just by being implemented and used as I did in the previous tip. The fact is, the transparency it provides is so apparent (isn't that an oxy-moron - 'apparent transparency'?) that it is hard not to understand the value it can provide. In that sense, this tip should be a good one, as I plan to mostly use code examples to get through the real world examples of the different bindings that it can perform.

Beyond a Trivial Example

Yesterday's tip was, unfortunately, a little trivial. I covered binding a couple simple bean properties to a few view components - but when you get into real world applications, that just doesn't cut the metaphorical mustard. So what I want to do now is cover other components in either a cursory glance, or if the situation merits, some more detailed examples to show the different patterns of usage. Also, I will commonly be using the BasicComponentFactory and other similar classes in this example. I will NOT be exercising all possible methods available - many of these methods/constructors take many variations of the parameters I pass - so do some digging. The best way to do that digging is to look at the API documentation for each adapter for view elements - and while I'm at it, before I move forward, a comprehensive list of adaptations for view elements can be found in /docs/guide/viewadapters.html in your downloaded binding framework folder... what do you mean you didn't download the binding framework yet? GO GET IT! .

Many of the bindable components can be approached in the exact same way as our textfield and checkbox from yesterday. For instance, JToggleButton and JCheckBoxMenuItem are handled exactly the same as JCheckBox elements. Likewise, JTextArea and JPasswordField are handled exactly the same as JTextField. Because of that, I don't see it being worth my time or yours to detail how to create/bind them here - shouldn't be too hard to get from A->B if you catch my drift. There are some wierd cases however, so keep reading.

Binding a Radio Button to a Field

Ok - wierd item one - radio buttons. Radio buttons turn out to be quite easy to bind. Multiple radio buttons in the same button group are assigned to a single value model, but each one is given a unique value to set on the bean property when selected. Ok sorry, again there I go with the words. Here is a code example that uses our existing MyBean.java class, and provides two choices for a value on the stringValue field (note, the exact same is possible for JRadioButtonMenuItem elements):

public class Binding {
 
 public static void main(String[] args) {
 
  MyBean bean = new MyBean();
  
  // Bean adapter is an adapter that can create many value model objects for a single 
  // bean. It is more efficient than the property adapter. The 'true' once again means 
  // we want it to observe our bean for changes.
  BeanAdapter adapter = new BeanAdapter(bean, true);
  
  // set the string value to one of the radio button's associated values
  bean.setStringValue("value1");
  
  ValueModel booleanModel = adapter.getValueModel("booleanValue");
  ValueModel stringModel = adapter.getValueModel("stringValue");
  // creates a JCheckBox with the property adapter providing the underlying model.
  JCheckBox box = BasicComponentFactory.createCheckBox(booleanModel, "Boolean Value");
  // create two radio buttons... 1st one binds 'value1' to 'stringValue'
  // 2nd one binds 'value2'.
  JRadioButton button1 = BasicComponentFactory.createRadioButton(stringModel, "value1", "Value 1");
  JRadioButton button2 = BasicComponentFactory.createRadioButton(stringModel, "value2", "Value 2");
  JFrame frame = new JFrame();
  frame.getContentPane().setLayout(new GridLayout(2,1));
  frame.getContentPane().add(box);
  frame.getContentPane().add(button1);
  frame.getContentPane().add(button2);
  frame.pack();
  frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
  frame.setVisible(true);
 }
}

Pretty easy, right? I'm impressed with the simplicity of this setup, and I'm also impressed that all is required to ensure that a radio button is selected from the group at initialization is simply setting that radio button's value on the bean itself (note this will also work once the components are actually bound together).

Binding a Bounded Slider to a Field

Woah, wait a minute. Sliders have always been a pain in the tropal tailbone to interact with effectively in Java. Not anymore. While for whatever reason the BasicComponentFactory and Bindings factories don't seem to have entries for the slider, all that is required is using a BoundedRangeAdapter object as the BoundedRangeModel on the slider, and setting it up for our bean's value model. Here is an example that sets up a slider with allowed values between 0 and 500. Notice in this example I dropped our booleanValue on the MyBean bean in favor of an intValue (as integers work just a *little* bit better with sliders).

// MyBean.java
import java.beans.PropertyChangeListener;
 
import com.jgoodies.binding.beans.*;
 
public class MyBean {
 // Note you don't HAVE to use this class - you can use
 // java.beans.PropertyChangeSupport if you want.
 private ExtendedPropertyChangeSupport changeSupport = new ExtendedPropertyChangeSupport(
   this);
 
 private int intValue;
 private String stringValue;
 
 public int getIntValue() {
  return intValue;
 }
 
 public void setIntValue(int newValue) {
  System.out.println("Boolean value set: " +newValue);
  int oldValue = intValue;
  intValue = newValue;
  changeSupport.firePropertyChange("intValue", oldValue, newValue);
 }
 
 public void addPropertyChangeListener(PropertyChangeListener x) {
  changeSupport.addPropertyChangeListener(x);
 }
 
 public void removePropertyChangeListener(PropertyChangeListener x) {
  changeSupport.removePropertyChangeListener(x);
 }
 
 public String getStringValue() {
  return stringValue;
 }
 
 public void setStringValue(String newValue) {
  System.out.println("String value set: "+  newValue);
  String oldValue = stringValue;
  this.stringValue = newValue;
  changeSupport.firePropertyChange("stringValue", oldValue, newValue);
 }
}
 
// Binding.java
import java.awt.GridLayout;
 
import javax.swing.*;
 
import com.jgoodies.binding.adapter.BasicComponentFactory;
import com.jgoodies.binding.adapter.BoundedRangeAdapter;
import com.jgoodies.binding.beans.BeanAdapter;
import com.jgoodies.binding.value.ValueModel;
 
public class Binding {
 
 public static void main(String[] args) {
 
  MyBean bean = new MyBean();
  
  // Bean adapter is an adapter that can create many value model objects for a single 
  // bean. It is more efficient than the property adapter. The 'true' once again means 
  // we want it to observe our bean for changes.
  BeanAdapter adapter = new BeanAdapter(bean, true);
  
  ValueModel intModel = adapter.getValueModel("intValue");
  ValueModel stringModel = adapter.getValueModel("stringValue");
  // creates a slider and a new bounded range adapter.
  // the range adapter is given our integer value model, and a range of 0-500.
  JSlider slider = new JSlider(new BoundedRangeAdapter(intModel, 0, 0, 500));
  JRadioButton button1 = BasicComponentFactory.createRadioButton(stringModel, "value1", "Value 1");
  JRadioButton button2 = BasicComponentFactory.createRadioButton(stringModel, "value2", "Value 2");
  JFrame frame = new JFrame();
  frame.getContentPane().setLayout(new GridLayout(2,1));
  frame.getContentPane().add(slider);
  frame.getContentPane().add(button1);
  frame.getContentPane().add(button2);
  frame.pack();
  frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
  frame.setVisible(true);
 }
}

Once again, a walk in the park.

Ok, so what about the less conventional widgets. What do I mean by conventional? Well, two widgets that for one reason or another don't implement an underlying model are the JLabel and the JFormattedTextField . What do we do if there is no model to adapt? Well, this is where we introduce the Property Connector .

Property Connectors

Property connectors are an interesting tool. The most common usage in the binding framework is for connecting non-modeled widgets to bean properties. Interestingly enough, however, it can be used more generally - simply to connect and synchronize multiple beans. Before I get ahead of myself though, let me explain what a property connector is. Property connectors differ from property adapters because they use the word connector instead of the word adapter. Ok, I can feel you pulling away from the hideousness of that joke. Seriously though, instead of connecting a widget's model to a bean, property connectors simply connect two bean properties. Thankfully, since most Swing elements follow (to at least some extent) the Javabean specification, any of the widgets that don't have a model, can be connected by using property connectors. This includes the setText on a JLabel and JFormattedTextField. Be aware, however, that PropertyConnectors make no attempt to convert types from one bean to another. That means that if you are using a JFormattedTextFields for dates, it better be bound to a field of java.util.Date type (and labels better be strings). Here is how a label is bound:

import java.awt.GridLayout;
 
import javax.swing.*;
 
import com.jgoodies.binding.adapter.BasicComponentFactory;
import com.jgoodies.binding.adapter.Bindings;
import com.jgoodies.binding.adapter.BoundedRangeAdapter;
import com.jgoodies.binding.beans.BeanAdapter;
import com.jgoodies.binding.value.ValueModel;
 
public class Binding {
 
 public static void main(String[] args) {
 
  MyBean bean = new MyBean();
  
  BeanAdapter adapter = new BeanAdapter(bean, true);
  
  ValueModel stringModel = adapter.getValueModel("stringValue");
  JLabel label = BasicComponentFactory.createLabel(stringModel);
  
  JFrame frame = new JFrame();
  frame.getContentPane().setLayout(new GridLayout(2,1));
  frame.getContentPane().add(label);
  frame.pack();
  frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
  frame.setVisible(true);
 }
}

Now you may be saying, "But JLabels aren't editable - binding them to a bean is a waste of time", and you'd be right. Just kidding - don't forget that these bindings are BI -directional. While the user can't edit the JLabel - some other behavior in the application (such as changing a JTextField) may have updated the bean. Because the JLabel is bound to the bean, it will automagically be updated! JFormattedTextFields are created in much the same way - re-listing the entire contents of the bean and the binding test would largely be repetitive here; just remember that the fields must be of the correct type!

Lists of Stuff

A-ha! I know what the binding framework doesn't support. JList s and JComboBox s. Well, no, actually it does. To start, here is how you can bind our existing MyBean instance to a single-selection JList (yes, I'm using the same old worn out bean, once again):

import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.List;
 
import javax.swing.*;
 
import com.jgoodies.binding.adapter.BasicComponentFactory;
import com.jgoodies.binding.adapter.Bindings;
import com.jgoodies.binding.adapter.BoundedRangeAdapter;
import com.jgoodies.binding.beans.BeanAdapter;
import com.jgoodies.binding.list.SelectionInList;
import com.jgoodies.binding.value.ValueModel;
 
public class Binding {
 
 public static void main(String[] args) {
 
  MyBean bean = new MyBean();
  
  BeanAdapter adapter = new BeanAdapter(bean, true);
  
  ValueModel intModel = adapter.getValueModel("intValue");
  ValueModel stringModel = adapter.getValueModel("stringValue");
  
  List possibleValues = new ArrayList();
  possibleValues.add("First Value");
  possibleValues.add("Second Value");
  possibleValues.add("Third Value");
  JList jlist = BasicComponentFactory.createList(new SelectionInList(possibleValues, stringModel, intModel));
  JFrame frame = new JFrame();
  frame.getContentPane().setLayout(new GridLayout(2,1));
  frame.getContentPane().add(jlist);
  frame.pack();
  frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
  frame.setVisible(true);
 }
}

Note that while in the above example, I provide the possible values explicitly, it is just as possible to get them directly from the bean (as another value model backed by a java.util.List ). As best as I can tell, there is (as of yet) no way to automatically bind a mulitple-selection list to a bean. I may be wrong about this, so don't take my word as gold, but short of implementing my own adapter (hah!), I haven't found any way to have a fully supported mulitple-select list. Incidentally, the class that performs adaptation of the selections is the com.jgoodies.binding.adapter.SingleListSelectionAdapter .

Combo boxes can be handled in a similar way to single-selection lists, although it can be a little less complicated (given the right constructor usage):

import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.List;
 
import javax.swing.*;
 
import com.jgoodies.binding.adapter.BasicComponentFactory;
import com.jgoodies.binding.adapter.Bindings;
import com.jgoodies.binding.adapter.BoundedRangeAdapter;
import com.jgoodies.binding.adapter.ComboBoxAdapter;
import com.jgoodies.binding.beans.BeanAdapter;
import com.jgoodies.binding.list.SelectionInList;
import com.jgoodies.binding.value.ValueModel;
 
public class Binding {
 
 public static void main(String[] args) {
 
  MyBean bean = new MyBean();
  
  BeanAdapter adapter = new BeanAdapter(bean, true);
  
  ValueModel intModel = adapter.getValueModel("intValue");
  ValueModel stringModel = adapter.getValueModel("stringValue");
  
  List possibleValues = new ArrayList();
  possibleValues.add("First Value");
  possibleValues.add("Second Value");
  possibleValues.add("Third Value");
  JComboBox comboBox = new JComboBox(new ComboBoxAdapter(possibleValues, stringModel));
  JFrame frame = new JFrame();
  frame.getContentPane().setLayout(new GridLayout(2,1));
  frame.getContentPane().add(comboBox);
  frame.pack();
  frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
  frame.setVisible(true);
 }
}

Whew! Well, I'm about beat for this session of JGoodies Bindings. I hope you learned a little about binding various 'real world' widgets to your beans. Don't go scurrying off yet, however. Next on the agenda is to spend more time understanding the more advanced benefits that can be found by using the value model intermediaries. To do some name dropping, this includes usage of the PresentationModel class, the BufferedValueModel , Triggers and a few others. Finally, two tips from now I want to finish out my look at the binding framework by discussing some helpful classes that ship with it, but aren't neccessarily directly needed. If time merits, I'll also discuss some of the extras, and if I'm feeling really persistent I'll also discuss the super-ultra-top-secret-advanced features.

Until next time,

R.J. Lorimer
rj -at- javalobby.org
http://www.coffee-bytes.com

1 . At 8:25 AM on Mar 10, 2005, Steven Bell wrote:
  Click to reply to this thread Reply

Re: JGoodies: Understanding Binding - Part 2

This looks like a very cool framework. Ever since I started working with Tapestry and Hibernate (two frameworks that provide data mapping) I've wondered why we didn't have something like this for Swing. Glad to see it's out there.

I might try adapting an existing app I have to this. If I do I'll post my results. Need to see how it handles JFormattedTextFields though, have a ton of those. :)

Keep up the good work.
2 . At 4:28 AM on Apr 13, 2005, Luca Liberti wrote:
  Click to reply to this thread Reply

Re: JGoodies: Understanding Binding - Part 2

Pretty cool!
I am using the framework on a swing application I started
building and it seems very helpful, however I cannot find in the article a good description of the behaviour of the PropertyConnectors.
In the example it is not really explained how to use them, while they are clearly useful in all the situations where custom components are used. In my case I developed a TextBox that holds a Double value and I wanted to bind it to a Double property but I couldn't manage to get it to work with the usual PropertyAdapter I guess because the getValue of my control retruns a Double instead of a String.
3 . At 8:30 AM on Apr 13, 2005, R.J. Lorimer wrote:
  Click to reply to this thread Reply

Re: JGoodies: Understanding Binding - Part 2

Luca,

PropertyConnectors for binding are useful when you have no Swing model to stand on.

In general, property connectors are useful for glue-ing two properties together on two different beans. Let's say you have two beans like this:

public class BeanA {
 
 private ExtendedPropertyChangeSupport changeSupport = new ExtendedPropertyChangeSupport(
   this);
 
 private String valueA;
 
 public void setValueA(String newValueA) {
  String oldValueA = valueA;
  valueA = newValueA;
  changeSupport.firePropertyChange("valueA, oldValueA, newValueA);
 }
 
 public String getValueA() {
  return valueA;
 }
 
}


public class BeanB {
 
 private ExtendedPropertyChangeSupport changeSupport = new ExtendedPropertyChangeSupport(
   this);
 
 private String valueB;
 
 public void setValueB(String newValueB) {
  String oldValueB = valueB;
  valueB = newValueB;
  changeSupport.firePropertyChange("valueB", oldValueB, newValueB);
 }
 
 public String getValueB() {
  return valueB;
 }
 
}


If you wanted to, you can then glue those two beans properties (valueA, valueB) together (notice there is no Swing code here) by using a property connector:

BeanA beanA = new BeanA();
BeanB beanB = new BeanB();
PropertyConnector.connect(beanA, "valueA", beanB, "valueB");
 
beanA.setValueA("blah"); // sets valueA, and then triggers a set on beanB
System.out.println(beanB.getValueB()); // prints 'blah'
beanB.setValueB("kaboom"); // sets valueB, and then triggers a set on beanA
System.out.println(beanA.getValueA()); // prints 'kaboom'


With regard to your 'textbox' - should I assume this custom connector simply extends JComponent? Or does it extend JTextComponent, or something more specific? Understanding that will bring me a lot closer to understanding what problem you are having.
Best, R.J. Lorimer
4 . At 9:41 AM on Apr 13, 2005, Luca Liberti wrote:
  Click to reply to this thread Reply

Re: JGoodies: Understanding Binding - Part 2

Thank you very much for the tips.
My textbox is used to limit the user input to floating point numbers with a given number of decimal places and
values falling within a given interval. It extends JTextbox and has a custom Document that extends PlainDocument to perform checks on the input while the user is typing. The document has a value property of type Double. I am not assuming this is the most elegant solution to the problem but It is the best I could think of at the moment.

What I did in order to bind the document value was to:
1) Add a PropertyChangeSupport to the document class:

private PropertyChangeSupport changeSupport = new PopertyChangeSupport(this)

2) Add the two methods to add and remove PropertyChangeListeners:

public void addPropertyChangeListener(PropertyChangeListener x) {
changeSupport.addPropertyChangeListener(x);
}

public void removePropertyChangeListener(PropertyChangeListener x) {
changeSupport.removePropertyChangeListener(x);
}

3) fire the the PropertyChangeEvent within the setValue(Double newValue) method:
changeSupport.firePropertyChange("value",OldValue,newValue);

Similarly to the examples, I added in the main method of the test class a PropertyConnector to bind the document to a Double field in domain class bean:

PropertyConnector connector =
new PropertyConnector(doubleTextBox.getDocument(), "value",doubleModel, "value");

where doubleModel is the valueModel conneted to the bean.

BeanAdapter adapter = new BeanAdapter(bean, true);
ValueModel doubleModel = adapter.getValueModel("doubleValue");

I didn't get the thing working at the beginning because I mistakenly assigned the OldValue parameter in the firePropertyChange of the setValue method of the document class to the newValue so that the actual method call was:

changeSupport.firePropertyChange("value",newValue,newValue);

which did not cause any call to the domain class bean setter method.
5 . At 6:53 AM on May 15, 2005, Chris Murphy wrote:
  Click to reply to this thread Reply

Re: JGoodies: Understanding Binding - Part 2

For an alternative look at binding check out:

http://www.strandz.org

With Strandz you use a class called 'Attribute' to do the binding. There is also a Designer available which takes all the work out of the mapping of screen items to data object fields. And the concepts go a little further than just mapping - there are 'master detail' and 'lookup' as well. Once you've done all the mapping work these two concepts put it all into productive action.
6 . At 4:45 AM on Apr 18, 2007, Ankit Jain wrote:
  Click to reply to this thread Reply

JGoodies: Understanding Binding - Part 2

I want to Connect JCheckBox and JComboBox through
PropertyConnector.

if JCheckBox is selected then JComboBox should be Visible
and if JCheckBox is deselected then JComboBox should be
Invisible.

thread.rss_message