Handling Bound Property Change Events in JAVA
Posted On September 24, 2005 by Priyadarshan Roy filed under Java
Java programmers must be aware of Java Beans used in Java Applications. If not, let us have a quick look into it. We shall then proceed with the implementation of Property Change Events in Java Beans.
Java Bean is simply a class object having private properties but public functions to access those properties. They are reusable components that can be accessed by any object. These properties are accessible only through the functions or say their accessors and mutators (getters and setters); mutators should be setXxx() and accessors should be getXxx(), where Xxx is the name of a private instance variable defined in the Bean. Access Modifier of these setter and getters should be public so that they can be accessible from the outside class.
For example, LoginBean has two private properties and their accessors and mutators are as given in code 1.
Code 1
public class LoginBean {
private String username;
private String password;
public void setUsername(String user) {
this.username = user;
}
public String getUsername() {
return username;
}
public void setPassword(String pass) {
this.password = pass;
}
public String getPassword() {
return password;
}
}
Code 1 is an example of a Java Bean called LoginBean having two properties – username and password, with setUsername() and setPassword() as mutators and getUsername() and getPassword() as accessors, respectively.
Now, let us move on with a java application listening to changes in the property of a bean. In the real world, when your friend’s phone number changes, you are informed about the change. Similarly, when a bean’s property is altered, beans listening to the property must be informed by the bean about the changes. Such properties of bean that provide notification to other beans are called ‘Bound Properties’.
To implement bound properties, you must use PropertyChangeSupport class and its methods. An object of this class must maintain a list of beans listening to the property change. An object of the PropertyChangeEvent class is sent to the listening beans when there are any changes in the value of the bound property.
Let us study an example, FontEditor having newFont as bound property and a java stand-alone application HelloWorld listening to the changes. If the value of newFont property changes, the Font in HelloWorld application (which is listening to the bean) changes.
We will first create a java bean FontEditor having bound property newFont. Refer code 2.
Here, newFont is an instance variable of type Font. Constructor of Font class takes font-type, style and size as arguments. Hence, changes in any of the three values would change the newFont value, which would be informed to the listeners.
Code 2
// File: FontEditor.java
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.beans.*;
public class FontEditor extends JDialog {
private Font newFont = new Font("Times New Roman",Font.BOLD,12);
public Font getNewFont() {
return newFont;
}
public void setNewFont(Font f) {
newFont = f;
}
}
Our Java Bean is simply a dialog with newFont as bound property with its accessor and mutator. Code 3 takes you further…
Code 3
// File: FontEditor.java
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.beans.*;
public class FontEditor extends JDialog implements ActionListener{
private Font newFont = new Font("Times New Roman",Font.BOLD,12);
JComboBox cbfType,cbfStyle,cbfSize;
JButton btnOk,btnCancel;
public Font getNewFont(){
return newFont;
}
public void setNewFont(Font f){
newFont = f;
}
public FontEditor(Frame fr,String title){
super(fr,title);
// getting font family from the graphics environment.
GraphicsEnvironment gf = GraphicsEnvironment.getLocalGraphicsEnvironment();
String myfont[] = gf.getAvailableFontFamilyNames();
cbfType = new JComboBox(myfont);
add(cbfType);
String fontStyle[] = {"PLAIN","ITALIC","BOLD",};
cbfStyle = new JComboBox(fontStyle);
add(cbfStyle);
String fontSize[] = {"10","12","14","16","18","20","24","26","28","36","48","72"};
cbfSize = new JComboBox(fontSize);
add(cbfSize);
btnOk =new JButton("OK");
btnCancel =new JButton("Cancel");
add(btnOk);
add(btnCancel);
// adding action listener
btnOk.addActionListener(this);
btnCancel.addActionListener(this);
// setting layout and size for the dialog
setLayout(new FlowLayout());
setSize(170,170);
}
public void actionPerformed(ActionEvent ae){
if(ae.getSource()==btnOk){
String type = (String) cbfType.getSelectedItem();
String style = (String)cbfStyle.getSelectedItem();
int s = 0;
int size = Integer.parseInt((String)cbfSize.getSelectedItem());
if(style=="PLAIN")
s= Font.PLAIN;
else {
if(style =="BOLD")
s= Font.BOLD;
else
s= Font.ITALIC;
}
Font f = new Font(type,s,size);
System.out.println(type+s+size);
setNewFont(f);
}
else{
this.setVisible(false);
}
}
}
We have added three combo boxes (cbfType, cbfStyle, cbfSize) for font-type, font-style and font-size, respectively, and two buttons (btnOk, btnCancel) for enabling changes and to cancel the changes, respectively.
Actions to be taken when these buttons are clicked are added in the actionPerformed function. Note that Dialog also implements ActionListener interface, which is listened by two buttons (btnOk, btnCancel).
On click of btnOk button, values from the three combo boxes are taken and a new Font object created with these values. Then, setNewFont() is called to change the value of bound property newFont.
What’s next…?
Yes, here comes the real work for bean listeners. See code 4.
· We create an object of PropertyChangeSupport and pass bean in the argument of the constructor – here ‘this’ would make it;
· Then add two functions addPropertyChangeListener and removePropertyChangeListener, which are used to register listeners that keep track of changes in the newFont value;
· Then call firePropertyChange function, which would inform all the listeners about the changes in the value of bound property; and
· Save the code in FontEditor.java file.
Code 4
// File: FontEditor.java
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.beans.*;
public class FontEditor extends JDialog implements ActionListener {
private Font newFont = new Font("Times New Roman",Font.BOLD,12);
JComboBox cbfType,cbfStyle,cbfSize;
JButton btnOk,btnCancel;
protected PropertyChangeSupport changes = new PropertyChangeSupport(this);
public Font getNewFont(){
return newFont;
}
public void setNewFont(Font f){
Font old = newFont;
try{
changes.firePropertyChange("Font Changed",old,f);
newFont = f;
}
catch(Exception e){
System.out.println(e);
}
}
public FontEditor(Frame fr,String title){
super(fr,title);
// getting font family from the graphics environment.
GraphicsEnvironment gf = GraphicsEnvironment.getLocalGraphicsEnvironment();
String myfont[] = gf.getAvailableFontFamilyNames();
cbfType = new JComboBox(myfont);
add(cbfType);
String fontStyle[] = {"PLAIN","ITALIC","BOLD",};
cbfStyle = new JComboBox(fontStyle);
add(cbfStyle);
String fontSize[] = {"10","12","14","16","18","20","24","26","28","36","48","72"};
cbfSize = new JComboBox(fontSize);
add(cbfSize);
btnOk =new JButton("OK");
btnCancel =new JButton("Cancel");
add(btnOk);
add(btnCancel);
// adding action listener
btnOk.addActionListener(this);
btnCancel.addActionListener(this);
// setting layout and size for the dialog
setLayout(new FlowLayout());
setSize(170,170);
}
public void actionPerformed(ActionEvent ae){
if(ae.getSource()==btnOk){
String type = (String) cbfType.getSelectedItem();
String style = (String)cbfStyle.getSelectedItem();
int s = 0;
int size = Integer.parseInt((String)cbfSize.getSelectedItem());
if(style=="PLAIN")
s= Font.PLAIN;
else {
if(style =="BOLD")
s= Font.BOLD;
else
s= Font.ITALIC;
}
Font f = new Font(type,s,size);
setNewFont(f);
}
else{
this.setVisible(false);
}
}
public void addPropertyChangeListener(PropertyChangeListener l){
changes.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l){
changes.removePropertyChangeListener(l);
}
}
So, our java bean is now ready to be implemented by any application. Implementation of such a bean is very simple’ you need to just implement an interface PropertyChangeListener in your application and provide implementation of function public void propertyChange(PropertyChangeEvent pcevent), which would include the action to be taken in response to changes in the value of bound property.
To keep our example short and simple, we will make a stand-alone application HelloWorld, which would be a frame having a panel with Text “HELLO WORLD” on which changes in the font value would be reflected.
Frame will have a menubar with a menu Edit and menuItem Font. On click of Font menuItem, the FontEditor Dialog Box opens. On changing the font value, Font of Message on the panel changes (code 5).
Code 5
// File: HelloWorld.java
import javax.swing.*;
import java.beans.*;
import java.awt.*;
import java.awt.event.*;
public class HelloWorld extends JFrame implements ActionListener, PropertyChangeListener
{
JLabel lblMessage;
JPanel panel;
JMenuBar actionBar;
JMenu file,edit;
JMenuItem changeFont;
FontEditor fe = new FontEditor(this,"Font Editor");
public HelloWorld(){
super(“Hello World”);
panel = new JPanel();
Font f = new Font("Times New Roman",Font.BOLD,24);
lblMessage = new JLabel("HELLO WORLD",SwingConstants.CENTER);
lblMessage.setFont(f);
panel.add(lblMessage);
actionBar = new JMenuBar();
file = new JMenu("File");
edit = new JMenu("Edit");
changeFont = new JMenuItem("Font");
actionBar.add(file);
actionBar.add(edit);
edit.add(changeFont);
changeFont.addActionListener(this);
fe.addPropertyChangeListener(this);
add(actionBar,BorderLayout.NORTH);
add(panel,BorderLayout.CENTER);
setSize(400,200);
setVisible(true);
}
public void propertyChange(PropertyChangeEvent pcevent){
Font newFt = (Font)pcevent.getNewValue();
lblMessage.setFont(newFt);
}
public void actionPerformed(ActionEvent evt){
fe.setVisible(true);
}
public static void main(String argv[]) {
new HelloWorld();
}
}
Save the code in HelloWorld.java file.
· Now compile both the files:
javac *.java ; and
· Run the application:
java HelloWorld.
Click on Edit -> Font. FontEditor Dialog appears. Refer figures 1 and 2.


Change the Font and click OK button. The modifications will be reflected in the HelloWorld application.
The author can be contacted at: shradhdha.dave@lycos.com.
Java Bean is simply a class object having private properties but public functions to access those properties. They are reusable components that can be accessed by any object. These properties are accessible only through the functions or say their accessors and mutators (getters and setters); mutators should be setXxx() and accessors should be getXxx(), where Xxx is the name of a private instance variable defined in the Bean. Access Modifier of these setter and getters should be public so that they can be accessible from the outside class.
For example, LoginBean has two private properties and their accessors and mutators are as given in code 1.
Code 1
public class LoginBean {
private String username;
private String password;
public void setUsername(String user) {
this.username = user;
}
public String getUsername() {
return username;
}
public void setPassword(String pass) {
this.password = pass;
}
public String getPassword() {
return password;
}
}
Code 1 is an example of a Java Bean called LoginBean having two properties – username and password, with setUsername() and setPassword() as mutators and getUsername() and getPassword() as accessors, respectively.
Now, let us move on with a java application listening to changes in the property of a bean. In the real world, when your friend’s phone number changes, you are informed about the change. Similarly, when a bean’s property is altered, beans listening to the property must be informed by the bean about the changes. Such properties of bean that provide notification to other beans are called ‘Bound Properties’.
To implement bound properties, you must use PropertyChangeSupport class and its methods. An object of this class must maintain a list of beans listening to the property change. An object of the PropertyChangeEvent class is sent to the listening beans when there are any changes in the value of the bound property.
Let us study an example, FontEditor having newFont as bound property and a java stand-alone application HelloWorld listening to the changes. If the value of newFont property changes, the Font in HelloWorld application (which is listening to the bean) changes.
We will first create a java bean FontEditor having bound property newFont. Refer code 2.
Here, newFont is an instance variable of type Font. Constructor of Font class takes font-type, style and size as arguments. Hence, changes in any of the three values would change the newFont value, which would be informed to the listeners.
Code 2
// File: FontEditor.java
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.beans.*;
public class FontEditor extends JDialog {
private Font newFont = new Font("Times New Roman",Font.BOLD,12);
public Font getNewFont() {
return newFont;
}
public void setNewFont(Font f) {
newFont = f;
}
}
Our Java Bean is simply a dialog with newFont as bound property with its accessor and mutator. Code 3 takes you further…
Code 3
// File: FontEditor.java
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.beans.*;
public class FontEditor extends JDialog implements ActionListener{
private Font newFont = new Font("Times New Roman",Font.BOLD,12);
JComboBox cbfType,cbfStyle,cbfSize;
JButton btnOk,btnCancel;
public Font getNewFont(){
return newFont;
}
public void setNewFont(Font f){
newFont = f;
}
public FontEditor(Frame fr,String title){
super(fr,title);
// getting font family from the graphics environment.
GraphicsEnvironment gf = GraphicsEnvironment.getLocalGraphicsEnvironment();
String myfont[] = gf.getAvailableFontFamilyNames();
cbfType = new JComboBox(myfont);
add(cbfType);
String fontStyle[] = {"PLAIN","ITALIC","BOLD",};
cbfStyle = new JComboBox(fontStyle);
add(cbfStyle);
String fontSize[] = {"10","12","14","16","18","20","24","26","28","36","48","72"};
cbfSize = new JComboBox(fontSize);
add(cbfSize);
btnOk =new JButton("OK");
btnCancel =new JButton("Cancel");
add(btnOk);
add(btnCancel);
// adding action listener
btnOk.addActionListener(this);
btnCancel.addActionListener(this);
// setting layout and size for the dialog
setLayout(new FlowLayout());
setSize(170,170);
}
public void actionPerformed(ActionEvent ae){
if(ae.getSource()==btnOk){
String type = (String) cbfType.getSelectedItem();
String style = (String)cbfStyle.getSelectedItem();
int s = 0;
int size = Integer.parseInt((String)cbfSize.getSelectedItem());
if(style=="PLAIN")
s= Font.PLAIN;
else {
if(style =="BOLD")
s= Font.BOLD;
else
s= Font.ITALIC;
}
Font f = new Font(type,s,size);
System.out.println(type+s+size);
setNewFont(f);
}
else{
this.setVisible(false);
}
}
}
We have added three combo boxes (cbfType, cbfStyle, cbfSize) for font-type, font-style and font-size, respectively, and two buttons (btnOk, btnCancel) for enabling changes and to cancel the changes, respectively.
Actions to be taken when these buttons are clicked are added in the actionPerformed function. Note that Dialog also implements ActionListener interface, which is listened by two buttons (btnOk, btnCancel).
On click of btnOk button, values from the three combo boxes are taken and a new Font object created with these values. Then, setNewFont() is called to change the value of bound property newFont.
What’s next…?
Yes, here comes the real work for bean listeners. See code 4.
· We create an object of PropertyChangeSupport and pass bean in the argument of the constructor – here ‘this’ would make it;
· Then add two functions addPropertyChangeListener and removePropertyChangeListener, which are used to register listeners that keep track of changes in the newFont value;
· Then call firePropertyChange function, which would inform all the listeners about the changes in the value of bound property; and
· Save the code in FontEditor.java file.
Code 4
// File: FontEditor.java
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.beans.*;
public class FontEditor extends JDialog implements ActionListener {
private Font newFont = new Font("Times New Roman",Font.BOLD,12);
JComboBox cbfType,cbfStyle,cbfSize;
JButton btnOk,btnCancel;
protected PropertyChangeSupport changes = new PropertyChangeSupport(this);
public Font getNewFont(){
return newFont;
}
public void setNewFont(Font f){
Font old = newFont;
try{
changes.firePropertyChange("Font Changed",old,f);
newFont = f;
}
catch(Exception e){
System.out.println(e);
}
}
public FontEditor(Frame fr,String title){
super(fr,title);
// getting font family from the graphics environment.
GraphicsEnvironment gf = GraphicsEnvironment.getLocalGraphicsEnvironment();
String myfont[] = gf.getAvailableFontFamilyNames();
cbfType = new JComboBox(myfont);
add(cbfType);
String fontStyle[] = {"PLAIN","ITALIC","BOLD",};
cbfStyle = new JComboBox(fontStyle);
add(cbfStyle);
String fontSize[] = {"10","12","14","16","18","20","24","26","28","36","48","72"};
cbfSize = new JComboBox(fontSize);
add(cbfSize);
btnOk =new JButton("OK");
btnCancel =new JButton("Cancel");
add(btnOk);
add(btnCancel);
// adding action listener
btnOk.addActionListener(this);
btnCancel.addActionListener(this);
// setting layout and size for the dialog
setLayout(new FlowLayout());
setSize(170,170);
}
public void actionPerformed(ActionEvent ae){
if(ae.getSource()==btnOk){
String type = (String) cbfType.getSelectedItem();
String style = (String)cbfStyle.getSelectedItem();
int s = 0;
int size = Integer.parseInt((String)cbfSize.getSelectedItem());
if(style=="PLAIN")
s= Font.PLAIN;
else {
if(style =="BOLD")
s= Font.BOLD;
else
s= Font.ITALIC;
}
Font f = new Font(type,s,size);
setNewFont(f);
}
else{
this.setVisible(false);
}
}
public void addPropertyChangeListener(PropertyChangeListener l){
changes.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l){
changes.removePropertyChangeListener(l);
}
}
So, our java bean is now ready to be implemented by any application. Implementation of such a bean is very simple’ you need to just implement an interface PropertyChangeListener in your application and provide implementation of function public void propertyChange(PropertyChangeEvent pcevent), which would include the action to be taken in response to changes in the value of bound property.
To keep our example short and simple, we will make a stand-alone application HelloWorld, which would be a frame having a panel with Text “HELLO WORLD” on which changes in the font value would be reflected.
Frame will have a menubar with a menu Edit and menuItem Font. On click of Font menuItem, the FontEditor Dialog Box opens. On changing the font value, Font of Message on the panel changes (code 5).
Code 5
// File: HelloWorld.java
import javax.swing.*;
import java.beans.*;
import java.awt.*;
import java.awt.event.*;
public class HelloWorld extends JFrame implements ActionListener, PropertyChangeListener
{
JLabel lblMessage;
JPanel panel;
JMenuBar actionBar;
JMenu file,edit;
JMenuItem changeFont;
FontEditor fe = new FontEditor(this,"Font Editor");
public HelloWorld(){
super(“Hello World”);
panel = new JPanel();
Font f = new Font("Times New Roman",Font.BOLD,24);
lblMessage = new JLabel("HELLO WORLD",SwingConstants.CENTER);
lblMessage.setFont(f);
panel.add(lblMessage);
actionBar = new JMenuBar();
file = new JMenu("File");
edit = new JMenu("Edit");
changeFont = new JMenuItem("Font");
actionBar.add(file);
actionBar.add(edit);
edit.add(changeFont);
changeFont.addActionListener(this);
fe.addPropertyChangeListener(this);
add(actionBar,BorderLayout.NORTH);
add(panel,BorderLayout.CENTER);
setSize(400,200);
setVisible(true);
}
public void propertyChange(PropertyChangeEvent pcevent){
Font newFt = (Font)pcevent.getNewValue();
lblMessage.setFont(newFt);
}
public void actionPerformed(ActionEvent evt){
fe.setVisible(true);
}
public static void main(String argv[]) {
new HelloWorld();
}
}
Save the code in HelloWorld.java file.
· Now compile both the files:
javac *.java ; and
· Run the application:
java HelloWorld.
Click on Edit -> Font. FontEditor Dialog appears. Refer figures 1 and 2.


Change the Font and click OK button. The modifications will be reflected in the HelloWorld application.
The author can be contacted at: shradhdha.dave@lycos.com.
