Jump to content

Into Java - Part VII: Difference between revisions

From EDM2
No edit summary
Ak120 (talk | contribs)
mNo edit summary
 
(6 intermediate revisions by 2 users not shown)
Line 1: Line 1:
By [[Simon Gronlund]]
{{IntoJava}}
''By [[Simon Grönlund]]''


{| width="400" cellpadding="4"
In spite of the lovely Swedish summer I will do my best to give you more parts of OOP to build Java applications with. We have already used a number of bricks not yet examined. Hence this column will explain some of them and give us a few more bricks and will move us closer to what I think all of you are longing for - graphical user interface programming.
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part I|Part I]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part II|Part II]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part III|Part III]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part IV|Part IV]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part V|Part V]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part VI|Part VI]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part VII|Part VII]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part VIII|Part VIII]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part IX|Part IX]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part X|Part X]]
|}
 
{| width="400" cellpadding="4"
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part XI|Part XI]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part XII|Part XII]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part XIII|Part XIII]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part XIV|Part IV]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part XV|Part XV]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part XVI|Part XVI]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part XVII|Part XVII]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part XVIII|Part XVIII]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part XIX|Part XIX]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part XX|Part XX]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part XXI|Part XXI]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part XXII|Part XXII]]
| align="CENTER" valign="MIDDLE" |
[[Into Java - Part XXIII|Part XXIII]]
|}
 
<font size="-1" face="Helv,Helvetica,Arial">In spite of the lovely Swedish summer I will do my best to give you more parts of OOP to build Java applications with. We have already used a number of bricks not yet examined. Hence this column will explain some of them and give us a few more bricks and will move us closer to what I think all of you are longing for--graphical user interface programming.


But to get the hang of GUIs we have to know about ''interface'' and ''event handling'' of which the latter is used to some extent. And when we are discussing those topics we may pay some attention to ''inner classes'' as well.
But to get the hang of GUIs we have to know about ''interface'' and ''event handling'' of which the latter is used to some extent. And when we are discussing those topics we may pay some attention to ''inner classes'' as well.
Line 59: Line 8:
Upon reading about inner classes you have to be aware of the complexity surrounding this topic. There is much to tell about how they are managed by the compiler, what a "local inner class" is, or what a "static inner class" is. We will be content with looking at ''anonymous inner classes'' since you have already used one a few times already. And close to this kind of a class we will examine the ''adapter''concept.
Upon reading about inner classes you have to be aware of the complexity surrounding this topic. There is much to tell about how they are managed by the compiler, what a "local inner class" is, or what a "static inner class" is. We will be content with looking at ''anonymous inner classes'' since you have already used one a few times already. And close to this kind of a class we will examine the ''adapter''concept.


The result of today's exercises will be a tiny frame with only two buttons able to change the color of the frame interior. But in fact, this will be a 'small step for you but a major leap for programming'. In the future we will be able to make ourselves much more complex and entertaining applications.<br /></font>
The result of today's exercises will be a tiny frame with only two buttons able to change the colour of the frame interior. But in fact, this will be a 'small step for you but a major leap for programming'. In the future we will be able to make ourselves much more complex and entertaining applications.
 
 
===<font face="Helv,Helvetica,Arial">'''Interface<br />'''</font>===
 
<font size="-1" face="Helv,Helvetica,Arial">A few columns ago I stated that Java does not allow inheritance from more than '''one''' other class. This way we avoid the dangers of multiple inheritance, the times you do not know exactly what is taking place or which super class is in use at a precise moment. A few programmers miss this dangerous feature--multiple inheritance--but Java offers a more robust and sound feature that we will examine, the ''interface''.


An interface is simply a promise that your class will implement the methods as they are signed in the interface. You tell the compiler by using the keyword</font><font size="-1"><tt> implements</tt></font><font size="-1" face="Helv,Helvetica,Arial">. Using interfaces you avoid not knowing how the other classes are working, you implement the method(s) in the actual class the way you like, and well in your hand. And that will be true for each interface you implement in a class, there is no limit to how many interfaces you may implement.
===Interface===
A few columns ago I stated that Java does not allow inheritance from more than '''one''' other class. This way we avoid the dangers of multiple inheritance, the times you do not know exactly what is taking place or which super class is in use at a precise moment. A few programmers miss this dangerous feature - multiple inheritance - but Java offers a more robust and sound feature that we will examine, the ''interface''.


Your class may implement these methods any way you like, but anyway the signature must be correct. Let us look at one of the most commonly used interfaces. That is</font><font size="-1"><tt> ActionListener </tt></font><font size="-1" face="Helv,Helvetica,Arial">that is frequently used in GUI applications. You find ActionListener in the package</font><font size="-1"><tt> java.awt.event</tt></font><font size="-1" face="Helv,Helvetica,Arial">, please look it up in your Java API. The source code looks like
An interface is simply a promise that your class will implement the methods as they are signed in the interface. You tell the compiler by using the keyword <tt>implements</tt>. Using interfaces you avoid not knowing how the other classes are working, you implement the method(s) in the actual class the way you like, and well in your hand. And that will be true for each interface you implement in a class, there is no limit to how many interfaces you may implement.


{| width="100%" cellpadding="2" bgcolor="#02B6FE"
Your class may implement these methods any way you like, but anyway the signature must be correct. Let us look at one of the most commonly used interfaces. That is <tt>ActionListener</tt> that is frequently used in GUI applications. You find ActionListener in the package <tt>java.awt.event</tt>, please look it up in your Java API. The source code looks like
|
{| width="100%" cellpadding="15" bgcolor="White"
| valign="Top" | <font size="-1">
<PRE>
<PRE>
/*
/*
Line 116: Line 58:
     public void actionPerformed(ActionEvent e);
     public void actionPerformed(ActionEvent e);
}
}
 
</PRE>
</PRE></font>
|}
|}
 
As seen when peeling the comments away the interface is only five lines long, so here is the short for them
As seen when peeling the comments away the interface is only five lines long, so here is the short for them
{| width="100%" cellpadding="2" bgcolor="#02B6FE"
|
{| width="100%" cellpadding="15" bgcolor="White"
| valign="Top" | <font size="-1">
<PRE>
<PRE>
package java.awt.event;
package java.awt.event;
Line 135: Line 68:
}
}
</PRE>
</PRE>
|}
We do not have to explore <tt>EventListener</tt> since it is even more sparse than <tt>ActionListener</tt> is, though it is the root of every listener interface.
|}
 
<font size="-1" face="Helv,Helvetica,Arial"><br clear="All" /> We do not have to explore</font><font size="-1"><tt> EventListener </tt></font><font size="-1" face="Helv,Helvetica,Arial">since it is even more sparse than</font><font size="-1"><tt> ActionListener </tt></font><font size="-1" face="Helv,Helvetica,Arial">is, though it is the root of every listener interface.
 
Out of interest in this code is that it does not contain nothing more than outlining of the method</font><font size="-1"><tt> actionPerformed(ActionEvent e) </tt></font><font size="-1" face="Helv,Helvetica,Arial">that has to be implemented in some way in the classes implementing the</font><font size="-1"><tt> ActionListener </tt></font><font size="-1" face="Helv,Helvetica,Arial">interface. The interface does not spell out how the method shall be written, it may be an empty method if you like to throw the events away. But the signature must be </font><font size="-1"><tt>(ActionEvent e)</tt></font><font size="-1" face="Helv,Helvetica,Arial">, and returning nothing. You may not try to use no parameter, a parameter of the wrong type or getting a return value from a void method. Your error will be found by javac so no harm is done, except that your blood pressure will increase.


{| cellspacing="5" cellpadding="10" align="Right" bgcolor="#02B6FE"
Out of interest in this code is that it does not contain nothing more than outlining of the method <tt>actionPerformed(ActionEvent e)</tt> that has to be implemented in some way in the classes implementing the <tt>ActionListener</tt> interface. The interface does not spell out how the method shall be written, it may be an empty method if you like to throw the events away. But the signature must be <tt>(ActionEvent e)</tt>, and returning nothing. You may not try to use no parameter, a parameter of the wrong type or getting a return value from a void method. Your error will be found by javac so no harm is done, except that your blood pressure will increase.
{| class="wikitable" align="Right"
|
|
<font size="-1" face="Helv,Helvetica,Arial">An empty method is simply a method that may look like:</font><br /><blockquote><font size="-1"><tt>public void myMethod(int i) {}</tt></font><br /></blockquote><font size="-1" face="Helv,Helvetica,Arial">That is, the curly braces contain nothing to do, the block is empty.<br /></font>
An empty method is simply a method that may look like:<br /><tt>public void myMethod(int i) {}</tt><br />That is, the curly braces contain nothing to do, the block is empty.
|}
|}
 
More complex interfaces might force you to implement many more methods, but still, the interface looks this tiny and slim. One example of a more complex interface is <tt>java.awt.event.MouseListener</tt> that you might look up and read. There you have to implement five methods, and most of them you may decide to implement as empty methods.
<font size="-1" face="Helv,Helvetica,Arial">More complex interfaces might force you to implement many more methods, but still, the interface looks this tiny and slim. One example of a more complex interface is</font><font size="-1"><tt> java.awt.event.MouseListener </tt></font><font size="-1" face="Helv,Helvetica,Arial">that you might look up and read. There you have to implement five methods, and most of them you may decide to implement as empty methods.


The conclusion of implementing an interface is: You promise to implement the methods of the interface. You do that anyway you like to, but they shall be implemented, and implemented with the correct signature.
The conclusion of implementing an interface is: You promise to implement the methods of the interface. You do that anyway you like to, but they shall be implemented, and implemented with the correct signature.


What is the gain then? Ahem, as implied this is pseudo inheritance, without the dangers coming by multiple inheritance. The gain is that we tell the compiler, and others reading our code, that we would like to use "multiple inheritance", andsince we at the same time make a promise we will not forget to implement necessary methods. Hence, interfaces makes our code more readable and forces ourselves to implement essential methods. Finally, we have full control over these methods.
What is the gain then? Ahem, as implied this is pseudo inheritance, without the dangers coming by multiple inheritance. The gain is that we tell the compiler, and others reading our code, that we would like to use "multiple inheritance", and since we at the same time make a promise we will not forget to implement necessary methods. Hence, interfaces makes our code more readable and forces ourselves to implement essential methods. Finally, we have full control over these methods.
 
Interfaces may be used to hold [../v5n1/intojava.html static constants], too. Please, look up</font><font size="-1"><tt> javax.swing.SwingConstants </tt></font><font size="-1" face="Helv,Helvetica,Arial">for an example. You access these static constants by for example</font><font size="-1"><tt> SwingConstants.HORIZONTAL </tt></font><font size="-1" face="Helv,Helvetica,Arial">(with path if necessary), as you do with any object variable. Note that static constants are spelled with capitals for readability, as outlined in the SUN Java Coding Style.


Is it possible to create your own interface? Of course, whenever you find a good reason to, you are perfectly free to implement an interface for both methods and/or static constants. The syntax is as shown above, but we make an example here</font>
Interfaces may be used to hold [static constants], too. Please, look up <tt>javax.swing.SwingConstants</tt> for an example. You access these static constants by for example <tt>SwingConstants.HORIZONTAL</tt> (with path if necessary), as you do with any object variable. Note that static constants are spelled with capitals for readability, as outlined in the SUN Java Coding Style.


{| width="100%" cellpadding="2" bgcolor="#02B6FE"
Is it possible to create your own interface? Of course, whenever you find a good reason to, you are perfectly free to implement an interface for both methods and/or static constants. The syntax is as shown above, but we make an example here
|
{| width="100%" cellpadding="15" bgcolor="White"
| valign="Top" | <font size="-1">
<PRE>
<PRE>
public interface MyInterface {
public interface MyInterface {
Line 171: Line 94:
}
}
</PRE>
</PRE>
</font>
|}
|}


<br clear="All" />
===Adapters===
In spite of most interfaces contain only one or a few methods to implement, some have plenty more to take care of. Two examples that I wouldn't like to implement are <tt>AccessibleComponent</tt> and <tt>TreeSelectionModel</tt> that have 27 methods each. Fortunately we do not use these interfaces that often, but you will find some interfaces tedious anyway since you will use them that frequently. Is there any way you do not have to implement that many methods each time you like to use these interfaces?


===<font face="Helv,Helvetica,Arial">'''Adapters<br />'''</font>===
In the frames we have used in earlier columns we have used the shortcut you are looking for. Look at the code below, and, please, rewrite it in an editor of your choice since we will extend this code to the little application we will develop together.
 
<font size="-1" face="Helv,Helvetica,Arial">In spite of most interfaces contain only one or a few methods to implement, some have plenty more to take care of. Two examples that I wouldn't like to implement are</font><font size="-1"><tt> AccessibleComponent </tt></font><font size="-1" face="Helv,Helvetica,Arial">and</font><font size="-1"><tt> TreeSelectionModel </tt></font><font size="-1" face="Helv,Helvetica,Arial">that have 27 methods each. Fortunately we do not use these interfaces that often, but you will find some interfaces tedious anyway since you will use them that frequently. Is there any way you do not have to implement that many methods each time you like to use these interfaces?
 
In the frames we have used in earlier columns we have used the shortcut you are looking for. Look at the code below, and, please, rewrite it in an editor of your choice since we will extend this code to the little application we will develop together.</font>
 
{| width="100%" cellpadding="2" bgcolor="#02B6FE"
|
{| width="100%" cellpadding="15" bgcolor="White"
| valign="Top" | <font size="-1">
<PRE>
<PRE>
import java.awt.event.*;
import java.awt.event.*;
Line 214: Line 126:
     }
     }
}
}
</PRE>
</PRE>
</font>
In the latter part of the constructor we see how we are adding a window listener. That is, we add something that will listen to any events we cause to the frame, by clicking the closing X or other events. Looking up <tt>java.awt.event.WindowAdapter</tt> in the Java API will show us that WindowAdapter '''is''' implementing <tt>WindowListener</tt>. <tt>WindowListener</tt> is an interface with seven methods to implement but using this convenience adapter we only have to implement the method of interest, <tt>windowClosing</tt>. In fact we have now made ourselves an anonymous inner class (that will be discussed in a moment).
|}
|}


<font size="-1" face="Helv,Helvetica,Arial"> <br clear="All" /> In the latter part of the constructor we see how we are adding a window listener. That is, we add something that will listen to any events we cause to the frame, by clicking the closing X or other events. Looking up</font><font size="-1"><tt> java.awt.event.WindowAdapter </tt></font><font size="-1" face="Helv,Helvetica,Arial">in the Java API will show us that WindowAdapter '''is''' implementing</font><font size="-1"><tt> WindowListener</tt></font><font size="-1" face="Helv,Helvetica,Arial">.</font><font size="-1"><tt> WindowListener </tt></font><font size="-1" face="Helv,Helvetica,Arial">is an interface with seven methods to implement but using this convenience adapter we only have to implement the method of interest,</font><font size="-1"><tt> windowClosing</tt></font><font size="-1" face="Helv,Helvetica,Arial">. In fact we have now made ourselves an anonymous inner class (that will be discussed in a moment).
What happened really? Let us look at the code line by line. We add a window listener that this time will be the convenient WindowAdapter, hence the <tt>new WindowAdapter()</tt> . But what is taking place after that? A curly brace encloses a block of all the methods you like to implement yourself, this time we only implement the <tt>public void windowClosing</tt> that takes a <tt>WindowEvent</tt> as parameter. The other six methods we do not touch and thus they will remain as they are implemented in the <tt>WindowAdapter</tt> class, that is they are empty. Our implementation of the <tt>windowClosing</tt> method is a plain request to the system to quit the application cleanly.


What happened really? Let us look at the code line by line. We add a window listener that this time will be the convenient WindowAdapter, hence the</font><font size="-1"><tt> new WindowAdapter()</tt></font><font size="-1" face="Helv,Helvetica,Arial">. But what is taking place after that? A curly brace encloses a block of all the methods you like to implement yourself, this time we only implement the</font><font size="-1"><tt> public void windowClosing </tt></font><font size="-1" face="Helv,Helvetica,Arial">that takes a</font><font size="-1"><tt> WindowEvent </tt></font><font size="-1" face="Helv,Helvetica,Arial">as parameter. The other six methods we do not touch and thus they will remain as they are implemented in the</font><font size="-1"><tt> WindowAdapter </tt></font><font size="-1" face="Helv,Helvetica,Arial">class, that is they are empty. Our implementation of the</font><font size="-1"><tt> windowClosing </tt></font><font size="-1" face="Helv,Helvetica,Arial">method is a plain request to the system to quit the application cleanly.
Adapters are used as convenience classes to spare us the tedious work of implementing many methods from interfaces, all of these implemented methods of adapters are empty, free to implement or to let be. You are not allowed to add variables within the "constructor block" though. Finally, adapters exist for every listener interface that have more than one method, at least as far as I am aware of.


Adapters are used as convenience classes to spare us the tedious work of implementing many methods from interfaces, all of these implemented methods of adapters are empty, free to implement or to let be. You are not allowed to add variables within the "constructor block" though. Finally, adapters exist for every listener interface that have more than one method, at least as far as I am aware of.<br /></font>
===Inner classes===
Most inner classes are classes that you hide within another class, within its borders. As an example, you might want to do a cannon ball game and you have implemented a special class that will react upon certain user response, as mouse clicks. This class you can easily hide within the borders of the main class of the game. Mostly such inner classes are listener classes, but inner classes may be any kind of class.


===<font face="Helv,Helvetica,Arial">'''Inner classes<br />'''</font>===
The profit of inner classes is that they can easily use data fields of the surrounding object. And further an inner class may be anonymous as seen above. As long as we do not need a reference to a certain object for later access we may chose to make an anonymous object. Upon compiling such code you will see that an unusual class appears in your listing
*FirstButtonFrame$1.class
*FirstButtonFrame.class
*FirstButtonFrame.java
The first line show us the anonymous class name, the context class name with a $1 added. My writings about these inner classes and anonymous such are merely at a premium, but as with any knowledge: it is hard to retrieve but has no weight when you later carry it.


<font size="-1" face="Helv,Helvetica,Arial">Most inner classes are classes that you hide within another class, within its borders. As an example, you might want to do a cannon ball game and you have implemented a special class that will react upon certain user response, as mouse clicks. This class you can easily hide within the borders of the main class of the game. Mostly such inner classes are listener classes, but inner classes may be any kind of class.
==Event handling==
A basic concept in any GUI programming of today is the event handling model, mostly explained in a way as the image shows. Most of the time the application will wait for user input, that raise an event that is caught by a listener that will examine the event object created (this is not always necessary, compare with our WindowAdapter that do not examine the WindowEvent but only calls the exit routine) and start some preset action.


The profit of inner classes is that they can easily use data fields of the surrounding object. And further an inner class may be anonymous as seen above. As long as we do not need a reference to a certain object for later access we may chose to make an anonymous object. Upon compiling such code you will see that an unusual class appears in your listing</font><br />
[[Image:java7.gif]]The actors necessary are:
*Event sources
*Listener(s)
*Event objects


* <font size="-1" face="Helv,Helvetica,Arial">FirstButtonFrame$1.class</font><br />
The event source may be a JButton. Whenever pressed you can imagine that it causes some kind of reaction within the computer. Any event source do that. They create an event object and send that object to any registered listener. So far we ask, what is that event object? And what is a registered listener?
* <font size="-1" face="Helv,Helvetica,Arial">FirstButtonFrame.class</font><br />
* <font size="-1" face="Helv,Helvetica,Arial">FirstButtonFrame.java</font><br />
 
<font size="-1" face="Helv,Helvetica,Arial">The first line show us the anonymous class name, the context class name with a $1 added. My writings about these inner classes and anonymous such are merely at a premium, but as with any knowledge: it is hard to retrieve but has no weight when you later carry it.<br /></font>
 
==<font face="Helv,Helvetica,Arial">'''Event handling<br />'''</font>==
 
<font size="-1" face="Helv,Helvetica,Arial">A basic concept in any GUI programming of today is the event handling model, mostly explained in a way as the image shows. Most of the time the application will wait for user input, that raise an event that is catched by a listener that will examine the event object created (this is not always necessary, compare with our WindowAdapter that do not examine the WindowEvent but only calls the exit routine) and start some preset action.<br /></font>
 
<font size="-1" face="Helv,Helvetica,Arial">[[Image:java7.gif]]The actors necessary are:</font><br />
 
* <font size="-1" face="Helv,Helvetica,Arial">Event sources</font><br />
* <font size="-1" face="Helv,Helvetica,Arial">Listener(s)</font><br />
* <font size="-1" face="Helv,Helvetica,Arial">Event objects</font><br />
 
<font size="-1" face="Helv,Helvetica,Arial">The event source may be a JButton. Whenever pressed you can imagine that it causes some kind of reaction within the computer. Any event source do that. They create an event object and send that object to any registered listener. So far we ask, what is that event object? And what is a registered listener?


We start with the listener. Any listener in the Java community implements one of the listener interfaces available. So, a class promises that it will implement one or more interfaces and each of those implementations, the implemented methods, acts as a listener to certain event objects.
We start with the listener. Any listener in the Java community implements one of the listener interfaces available. So, a class promises that it will implement one or more interfaces and each of those implementations, the implemented methods, acts as a listener to certain event objects.
Line 258: Line 160:
What are the EventObjects then? Quoted from the Java API: "All Event's are constructed with a reference to the object, the "source", that is logically deemed to be the object upon which the Event in question initially occurred upon." Yes, they are objects containing information that you might need whenever choosing what to do after the user input. For example, a MouseEvent object can give you the position of the mouse when a button was clicked, how many times it was clicked and upon which button of the common three mouse buttons. An ActionEvent from a JButton merely know which button was triggered and if any of the modifier keys were held down during this action event.
What are the EventObjects then? Quoted from the Java API: "All Event's are constructed with a reference to the object, the "source", that is logically deemed to be the object upon which the Event in question initially occurred upon." Yes, they are objects containing information that you might need whenever choosing what to do after the user input. For example, a MouseEvent object can give you the position of the mouse when a button was clicked, how many times it was clicked and upon which button of the common three mouse buttons. An ActionEvent from a JButton merely know which button was triggered and if any of the modifier keys were held down during this action event.


Let us add to the code we started out with. We will add one button and see what else is necessary then.</font>
Let us add to the code we started out with. We will add one button and see what else is necessary then.
 
{| width="100%" cellpadding="2" bgcolor="#02B6FE"
|
{| width="100%" cellpadding="15" bgcolor="White"
| valign="Top" | <font size="-1">
<PRE>
<PRE>
import java.awt.event.*;
import java.awt.event.*;
Line 304: Line 201:
}
}
</PRE>
</PRE>
</font>
|}
|}
<font size="-1" face="Helv,Helvetica,Arial"><br clear="All" />  <br /> Since JButtons creates</font><font size="-1"><tt> ActionEvent </tt></font><font size="-1" face="Helv,Helvetica,Arial">we states that we will implement the</font><font size="-1"><tt> ActionListener </tt></font><font size="-1" face="Helv,Helvetica,Arial">interface. Please note that in the code above we have still not done that, we have not kept our promise to implement the interface yet. Please, try to compile the class now and you will get the most weird error message, obviously javac got lost and tells you what might be a reasonable conclusion. Anyway, javac tells you that the class 'does not define the method void actionPerformed(java.awt.event.ActionEvent) from interface java.awt.event.ActionListener', that is correct, we have not. Please hold on a moment, and let us look at the other new lines first.


We know that we will refer to the</font><font size="-1"><tt> panel </tt></font><font size="-1" face="Helv,Helvetica,Arial">used to hold the buttons later on and thus declares the</font><font size="-1"><tt> panel </tt></font><font size="-1" face="Helv,Helvetica,Arial">as a private class variable of JPanel type. Within the constructor we then instantiate the</font><font size="-1"><tt> panel </tt></font><font size="-1" face="Helv,Helvetica,Arial">as a new JPanel.
Since JButtons creates <tt>ActionEvent</tt> we states that we will implement the <tt>ActionListener</tt> interface. Please note that in the code above we have still not done that, we have not kept our promise to implement the interface yet. Please, try to compile the class now and you will get the most weird error message, obviously javac got lost and tells you what might be a reasonable conclusion. Anyway, javac tells you that the class 'does not define the method void actionPerformed(java.awt.event.ActionEvent) from interface java.awt.event.ActionListener', that is correct, we have not. Please hold on a moment, and let us look at the other new lines first.


Continuing with the button we create a JButton with the visible title "White". It will automatically be instantiated with the proper size and the given title. Because we never have to refer to the button later on we do not need to declare it as a class variable. It is not forbidden, but why declare class variables when we do not need to? That will only fill the class with scrawl, and make it hard to read. The</font><font size="-1"><tt> panel </tt></font><font size="-1" face="Helv,Helvetica,Arial">will remember what is added to it, and that is enough.
We know that we will refer to the <tt>panel</tt> used to hold the buttons later on and thus declares the <tt>panel</tt> as a private class variable of JPanel type. Within the constructor we then instantiate the <tt>panel</tt> as a new JPanel.


Now the first step with event handling comes, adding an action listener. We have both an event source object, the JButton</font><font size="-1"><tt> butt</tt></font><font size="-1" face="Helv,Helvetica,Arial">, and an object that promises to act as a listener, this time it is the context itself and hence we add</font><font size="-1"><tt> this </tt></font><font size="-1" face="Helv,Helvetica,Arial">as the listening object.
Continuing with the button we create a JButton with the visible title "White". It will automatically be instantiated with the proper size and the given title. Because we never have to refer to the button later on we do not need to declare it as a class variable. It is not forbidden, but why declare class variables when we do not need to? That will only fill the class with scrawl, and make it hard to read. The <tt>panel</tt> will remember what is added to it, and that is enough.


The last line of the new lines might seem mysterious, </font><font size="-1"><tt>butt.setActionCommand("Button 1")</tt></font><font size="-1" face="Helv,Helvetica,Arial">. In a later column we will discuss how to take powerful advantage of this feature, but for now we leave that with a short explanation; if no</font><font size="-1"><tt> actionCommand </tt></font><font size="-1" face="Helv,Helvetica,Arial">is specified then JButton will use the text of the button as the</font><font size="-1"><tt> actionCommand</tt></font><font size="-1" face="Helv,Helvetica,Arial">. But whenever you specifically set a command, that one will be used and remembered. We will look to that in a few moments.
Now the first step with event handling comes, adding an action listener. We have both an event source object, the JButton <tt>butt</tt>, and an object that promises to act as a listener, this time it is the context itself and hence we add <tt>this</tt> as the listening object.


The last two lines are not new to us, we simply add the</font><font size="-1"><tt> panel </tt></font><font size="-1" face="Helv,Helvetica,Arial">to the</font><font size="-1"><tt> contentPane </tt></font><font size="-1" face="Helv,Helvetica,Arial">of the frame.<br /></font>
The last line of the new lines might seem mysterious, <tt>butt.setActionCommand("Button 1")</tt>. In a later column we will discuss how to take powerful advantage of this feature, but for now we leave that with a short explanation; if no <tt>actionCommand </tt> is specified then JButton will use the text of the button as the <tt>actionCommand</tt>. But whenever you specifically set a command, that one will be used and remembered. We will look to that in a few moments.


==='''The promise<br />'''===
The last two lines are not new to us, we simply add the <tt>panel</tt> to the <tt>contentPane</tt> of the frame.


<font size="-1" face="Helv,Helvetica,Arial">We promised to implement the interface ActionListener and thus we will add a method for that. The method has to have the following signature since that is specified in the interface:</font><br /><blockquote><font size="-1"><tt>public void actionPerformed(ActionEvent e)</tt></font><br /></blockquote><font size="-1" face="Helv,Helvetica,Arial">In fact, the only thing we might change is the name of the parameter variable, if it is a lengthy method we will make, you might chose a longer variable name, like</font><font size="-1"><tt> evt </tt></font><font size="-1" face="Helv,Helvetica,Arial">or</font><font size="-1"><tt> event</tt></font><font size="-1" face="Helv,Helvetica,Arial">. But except the parameter name, every letter have to be untouched. The code will look like<br /></font>
===The promise===
 
We promised to implement the interface ActionListener and thus we will add a method for that. The method has to have the following signature since that is specified in the interface:
{| width="100%" cellpadding="2" bgcolor="#02B6FE"
public void actionPerformed(ActionEvent e)
|
In fact, the only thing we might change is the name of the parameter variable, if it is a lengthy method we will make, you might chose a longer variable name, like <tt>evt</tt> or <tt>event</tt>. But except the parameter name, every letter have to be untouched. The code will look like
{| width="100%" cellpadding="15" bgcolor="White"
| valign="Top" | <font size="-1">
<PRE>
<PRE>
     public void actionPerformed(ActionEvent evt) {
     public void actionPerformed(ActionEvent evt) {
Line 341: Line 231:
     }
     }
</PRE>
</PRE>
</font>
Now you may compile the code and it works, but not much happens since we commented out the <tt>doButtonOne()</tt> method call. Anyway there is some output to the terminal window telling us "Button 1", so something is going on. The connection was, we made an object of the class and told it to show. Within the constructor block - constructors can be really long and nasty - we created a button object and added the class object as an action listener. Thereafter, any time you press the button an ActionEvent object is created and sent to the listener that loyally implemented the <tt>actionPerformed</tt> method, which take care of that object and simply asks it for the actionCommand we set to the button.
|}
|}
 
<font size="-1" face="Helv,Helvetica,Arial">Now you may compile the code and it works, but not much happens since we commented out the</font><font size="-1"><tt> doButtonOne() </tt></font><font size="-1" face="Helv,Helvetica,Arial">method call. Anyway there is some output to the terminal window telling us "Button 1", so something is going on. The connection was, we made an object of the class and told it to show. Within the constructor block--constructors can be really long and nasty--we created a button object and added the class object as an action listener. Thereafter, any time you press the button an ActionEvent object is created and sent to the listener that loyally implemented the</font><font size="-1"><tt> actionPerformed </tt></font><font size="-1" face="Helv,Helvetica,Arial">method, which take care of that object and simply asks it for the actionCommand we set to the button.
 
Since the actionCommand is always a text string we easily can test it against other text strings, but recall we have to make use of the method</font><font size="-1"><tt> equals</tt></font><font size="-1" face="Helv,Helvetica,Arial">, since the two text strings certainly are not the same object and hence the == test will not work. We merely print the action command string and then do a test. Let us add the</font><font size="-1"><tt> doButtonOne </tt></font><font size="-1" face="Helv,Helvetica,Arial">method after the</font><font size="-1"><tt> actionPerformed </tt></font><font size="-1" face="Helv,Helvetica,Arial">code.<br /></font>


{| width="100%" cellpadding="2" bgcolor="#02B6FE"
Since the actionCommand is always a text string we easily can test it against other text strings, but recall we have to make use of the method <tt>equals</tt>, since the two text strings certainly are not the same object and hence the == test will not work. We merely print the action command string and then do a test. Let us add the <tt>doButtonOne</tt> method after the <tt>actionPerformed</tt> code.
|
{| width="100%" cellpadding="15" bgcolor="White"
| valign="Top" | <font size="-1">
     private void doButtonOne() {
     private void doButtonOne() {
         System.out.println("is \"White\".");
         System.out.println("is \"White\".");
         panel.setBackground(Color.white);
         panel.setBackground(Color.white);
     }
     }
To prohibit illegal calls to this method we hide it using <tt>private</tt> and it will be visible only within the surrounding object. The method simply prints a small message, an extension to the former print made in the <tt>actionPerformed</tt> code. After that the panel background is set to white. Please, remember to the remove the comment marks <tt>//</tt> from the <tt>actionPerformed</tt> code, as well as the trailing comment at that line.


</font>
You might think that it is not necessary to make special methods for the actions taking place within <tt>doButtonOne()</tt>, and you are right of course. Only two lines do not justify a method of their own, so simply view this as an example code. It is, on the contrary, most common with lengthy and complex actions taking place after a user input. Thus it is wise to get the habit of using helper methods right away. With wisely chosen method names the code will be easily read as well, 'if this is true then this will happen, aha!'.
|}
|}
 
<font size="-1" face="Helv,Helvetica,Arial"> To prohibit illegal calls to this method we hide it using</font><font size="-1"><tt> private </tt></font><font size="-1" face="Helv,Helvetica,Arial">and it will be visible only within the surrounding object. The method simply prints a small message, an extension to the former print made in the</font><font size="-1"><tt> actionPerformed </tt></font><font size="-1" face="Helv,Helvetica,Arial">code. After that the panel background is set to white. Please, remember to the remove the comment marks</font><font size="-1"><tt> // </tt></font><font size="-1" face="Helv,Helvetica,Arial">from the </font><font size="-1"><tt>actionPerformed </tt></font><font size="-1" face="Helv,Helvetica,Arial">code, as well as the trailing comment at that line.
 
You might think that it is not necessary to make special methods for the actions taking place within</font><font size="-1"><tt> doButtonOne()</tt></font><font size="-1" face="Helv,Helvetica,Arial">, and you are right of course. Only two lines do not justify a method of their own, so simply view this as an example code. It is, on the contrary, most common with lengthy and complex actions taking place after a user input. Thus it is wise to get the habit of using helper methods right away. With wisely chosen method names the code will be easily read as well, 'if this is true then this will happen, aha!'.


The next step will of course be to add another button. The final code will look like this<br /></font>
The next step will of course be to add another button. The final code will look like this
 
{| width="100%" cellpadding="2" bgcolor="#02B6FE"
|
{| width="100%" cellpadding="15" bgcolor="White"
| valign="Top" | <font size="-1"><tt>
<PRE>
<PRE>
import java.awt.event.*;
import java.awt.event.*;
Line 441: Line 312:
}
}
</PRE>
</PRE>
The only peculiar thing with the code added is that we reuse the local variable name <tt>butt</tt>. That is OK since we do not like to hold references to any of the buttons. In fact, as soon as the constructor block is finished the local name <tt>butt</tt> will disappear and no longer exist. The panel holds the buttons and will remember their existence, but not their former and temporary names. If this coding style annoys you, you might use a new local variable name each new item created, but with several buttons or other items that seems to be a tedious work.


</tt></font>
Of course there are other small and new things in the code. An example of new things might be the <tt> \" </tt> that causes Java to print a quotation mark". But if there is anything, please use the forum and ask the question. I will answer any question I am able to answer about the Java columns.
|}
|}
 
<font size="-1" face="Helv,Helvetica,Arial">The only peculiar thing with the code added is that we reuse the local variable name</font><font size="-1"><tt> butt</tt></font><font size="-1" face="Helv,Helvetica,Arial">. That is OK since we do not like to hold references to any of the buttons. In fact, as soon as the constructor block is finished the local name</font><font size="-1"><tt> butt </tt></font><font size="-1" face="Helv,Helvetica,Arial">will disappear and no longer exist. The panel holds the buttons and will remember their existence, but not their former and temporary names. If this coding style annoys you, you might use a new local variable name each new item created, but with several buttons or other items that seems to be a tedious work.
 
Of course there are other small and new things in the code. An example of new things might be the</font><font size="-1"><tt> \" </tt></font><font size="-1" face="Helv,Helvetica,Arial">that causes Java to print a quotation mark". But if there is anything, please use the forum and ask the question. I will answer any question I am able to answer about the Java columns.<br /></font>
 
===<font face="Helv,Helvetica,Arial">'''Summary<br />'''</font>===
 
<font size="-1" face="Helv,Helvetica,Arial">Today we have looked at anonymity, and not only at anonymous inner classes but other minor objects, too. We have not used any inner class that we made ourselves but we have touched the idea though.


The main part of today's column was the event model, and if this seemed much to learn, stay rested. We will return to this topic many times and since we will continue with GUI programming we will discuss it over and over again. Anyway, you have to</font><br />
===Summary===
Today we have looked at anonymity, and not only at anonymous inner classes but other minor objects, too. We have not used any inner class that we made ourselves but we have touched the idea though.


# <font size="-1" face="Helv,Helvetica,Arial">Make a listener object, that implements a listener interface</font><br />
The main part of today's column was the event model, and if this seemed much to learn, stay rested. We will return to this topic many times and since we will continue with GUI programming we will discuss it over and over again. Anyway, you have to
# <font size="-1" face="Helv,Helvetica,Arial">Make an event source object, that creates event objects when triggered, and add the listener to it</font><br />
#Make a listener object, that implements a listener interface
# <font size="-1" face="Helv,Helvetica,Arial">Catch the event objects in a properly implemented method, maybe examine the message it conveys</font><br />
#Make an event source object, that creates event objects when triggered, and add the listener to it
#Catch the event objects in a properly implemented method, maybe examine the message it conveys


<font size="-1" face="Helv,Helvetica,Arial">Now I will leave town and go fishing, go pick some berries or mushrooms and enjoy the wonderful creation found in the nature. See you next month.<br /></font>
Now I will leave town and go fishing, go pick some berries or mushrooms and enjoy the wonderful creation found in the nature. See you next month.


<font size="-1" face="Helv,Helvetica,Arial">The FirstButtonFrame.java</font><br />
The FirstButtonFrame.java


[[Category:Languages Articles]]
[[Category:Java Articles]]

Latest revision as of 00:24, 28 May 2021

Into Java / Part
I II III IV V VI VII VIII IX X XI XII
XIII IV XV XVI XVII XVIII XIX XX XXI XXII XXIII

By Simon Grönlund

In spite of the lovely Swedish summer I will do my best to give you more parts of OOP to build Java applications with. We have already used a number of bricks not yet examined. Hence this column will explain some of them and give us a few more bricks and will move us closer to what I think all of you are longing for - graphical user interface programming.

But to get the hang of GUIs we have to know about interface and event handling of which the latter is used to some extent. And when we are discussing those topics we may pay some attention to inner classes as well.

Upon reading about inner classes you have to be aware of the complexity surrounding this topic. There is much to tell about how they are managed by the compiler, what a "local inner class" is, or what a "static inner class" is. We will be content with looking at anonymous inner classes since you have already used one a few times already. And close to this kind of a class we will examine the adapterconcept.

The result of today's exercises will be a tiny frame with only two buttons able to change the colour of the frame interior. But in fact, this will be a 'small step for you but a major leap for programming'. In the future we will be able to make ourselves much more complex and entertaining applications.

Interface

A few columns ago I stated that Java does not allow inheritance from more than one other class. This way we avoid the dangers of multiple inheritance, the times you do not know exactly what is taking place or which super class is in use at a precise moment. A few programmers miss this dangerous feature - multiple inheritance - but Java offers a more robust and sound feature that we will examine, the interface.

An interface is simply a promise that your class will implement the methods as they are signed in the interface. You tell the compiler by using the keyword implements. Using interfaces you avoid not knowing how the other classes are working, you implement the method(s) in the actual class the way you like, and well in your hand. And that will be true for each interface you implement in a class, there is no limit to how many interfaces you may implement.

Your class may implement these methods any way you like, but anyway the signature must be correct. Let us look at one of the most commonly used interfaces. That is ActionListener that is frequently used in GUI applications. You find ActionListener in the package java.awt.event, please look it up in your Java API. The source code looks like

/*
 * @(#)ActionListener.java 1.10 98/09/21
 *
 * Copyright 1996-1998 by Sun Microsystems, Inc.,
 * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information
 * of Sun Microsystems, Inc. ("Confidential Information"). You
 * shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement
 * you entered into with Sun.
 */
 
package java.awt.event;
import java.util.EventListener;
/**
 * The listener interface for receiving action events.
 * The class that is interested in processing an action event
 * implements this interface, and the object created with that
 * class is registered with a component, using the component's
 * <code>addActionListener</code> method. When the action event
 * occurs, that object's <code>actionPerformed</code> method is
 * invoked.
 *
 * @see ActionEvent
 * @see <a href="http://java.sun.com/docs/books/tutorial/post1.0 /ui/eventmodel.html">
   Tutorial: Java 1.1 Event Model</a>
 * @see <a href="http://www.awl.com/cp/javaseries/jcl1_2.html">
   Reference: The Java Class Libraries (update file)</a>
 *
 * @version 1.10 09/21/98
 * @author Carl Quinn
 */
 
public interface ActionListener extends EventListener {
    /**
     * Invoked when an action occurs.
     */
    public void actionPerformed(ActionEvent e);
}

As seen when peeling the comments away the interface is only five lines long, so here is the short for them

package java.awt.event;
import java.util.EventListener;
 
public interface ActionListener extends EventListener {
    public void actionPerformed(ActionEvent e);
}

We do not have to explore EventListener since it is even more sparse than ActionListener is, though it is the root of every listener interface.

Out of interest in this code is that it does not contain nothing more than outlining of the method actionPerformed(ActionEvent e) that has to be implemented in some way in the classes implementing the ActionListener interface. The interface does not spell out how the method shall be written, it may be an empty method if you like to throw the events away. But the signature must be (ActionEvent e), and returning nothing. You may not try to use no parameter, a parameter of the wrong type or getting a return value from a void method. Your error will be found by javac so no harm is done, except that your blood pressure will increase.

An empty method is simply a method that may look like:
public void myMethod(int i) {}
That is, the curly braces contain nothing to do, the block is empty.

More complex interfaces might force you to implement many more methods, but still, the interface looks this tiny and slim. One example of a more complex interface is java.awt.event.MouseListener that you might look up and read. There you have to implement five methods, and most of them you may decide to implement as empty methods.

The conclusion of implementing an interface is: You promise to implement the methods of the interface. You do that anyway you like to, but they shall be implemented, and implemented with the correct signature.

What is the gain then? Ahem, as implied this is pseudo inheritance, without the dangers coming by multiple inheritance. The gain is that we tell the compiler, and others reading our code, that we would like to use "multiple inheritance", and since we at the same time make a promise we will not forget to implement necessary methods. Hence, interfaces makes our code more readable and forces ourselves to implement essential methods. Finally, we have full control over these methods.

Interfaces may be used to hold [static constants], too. Please, look up javax.swing.SwingConstants for an example. You access these static constants by for example SwingConstants.HORIZONTAL (with path if necessary), as you do with any object variable. Note that static constants are spelled with capitals for readability, as outlined in the SUN Java Coding Style.

Is it possible to create your own interface? Of course, whenever you find a good reason to, you are perfectly free to implement an interface for both methods and/or static constants. The syntax is as shown above, but we make an example here

public interface MyInterface {
    public static final int NORTH = 0; // by degrees
    public static final int EAST = 90;
    public static final int SOUTH = 180;
    public static final int WEST = 270;
 
    public void whishedMethod(Parameter p);
}

Adapters

In spite of most interfaces contain only one or a few methods to implement, some have plenty more to take care of. Two examples that I wouldn't like to implement are AccessibleComponent and TreeSelectionModel that have 27 methods each. Fortunately we do not use these interfaces that often, but you will find some interfaces tedious anyway since you will use them that frequently. Is there any way you do not have to implement that many methods each time you like to use these interfaces?

In the frames we have used in earlier columns we have used the shortcut you are looking for. Look at the code below, and, please, rewrite it in an editor of your choice since we will extend this code to the little application we will develop together.

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class FirstButtonFrame extends JFrame {
 
    /* the constructor of this class */
    public FirstButtonFrame() {
         /* JFrame methods */
         setTitle("FirstButtonFrame");
         setLocation(100, 50);
         setSize(250, 100);
 
         addWindowListener(new WindowAdapter() {
             public void windowClosing(WindowEvent e) {
                  System.exit(0);
             }
         });
    }
 
    /* merely the driver */
    public static void main(String[] args) {
         FirstButtonFrame frame = new FirstButtonFrame();
         frame.show();
    }
}

In the latter part of the constructor we see how we are adding a window listener. That is, we add something that will listen to any events we cause to the frame, by clicking the closing X or other events. Looking up java.awt.event.WindowAdapter in the Java API will show us that WindowAdapter is implementing WindowListener. WindowListener is an interface with seven methods to implement but using this convenience adapter we only have to implement the method of interest, windowClosing. In fact we have now made ourselves an anonymous inner class (that will be discussed in a moment).

What happened really? Let us look at the code line by line. We add a window listener that this time will be the convenient WindowAdapter, hence the new WindowAdapter() . But what is taking place after that? A curly brace encloses a block of all the methods you like to implement yourself, this time we only implement the public void windowClosing that takes a WindowEvent as parameter. The other six methods we do not touch and thus they will remain as they are implemented in the WindowAdapter class, that is they are empty. Our implementation of the windowClosing method is a plain request to the system to quit the application cleanly.

Adapters are used as convenience classes to spare us the tedious work of implementing many methods from interfaces, all of these implemented methods of adapters are empty, free to implement or to let be. You are not allowed to add variables within the "constructor block" though. Finally, adapters exist for every listener interface that have more than one method, at least as far as I am aware of.

Inner classes

Most inner classes are classes that you hide within another class, within its borders. As an example, you might want to do a cannon ball game and you have implemented a special class that will react upon certain user response, as mouse clicks. This class you can easily hide within the borders of the main class of the game. Mostly such inner classes are listener classes, but inner classes may be any kind of class.

The profit of inner classes is that they can easily use data fields of the surrounding object. And further an inner class may be anonymous as seen above. As long as we do not need a reference to a certain object for later access we may chose to make an anonymous object. Upon compiling such code you will see that an unusual class appears in your listing

  • FirstButtonFrame$1.class
  • FirstButtonFrame.class
  • FirstButtonFrame.java

The first line show us the anonymous class name, the context class name with a $1 added. My writings about these inner classes and anonymous such are merely at a premium, but as with any knowledge: it is hard to retrieve but has no weight when you later carry it.

Event handling

A basic concept in any GUI programming of today is the event handling model, mostly explained in a way as the image shows. Most of the time the application will wait for user input, that raise an event that is caught by a listener that will examine the event object created (this is not always necessary, compare with our WindowAdapter that do not examine the WindowEvent but only calls the exit routine) and start some preset action.

The actors necessary are:

  • Event sources
  • Listener(s)
  • Event objects

The event source may be a JButton. Whenever pressed you can imagine that it causes some kind of reaction within the computer. Any event source do that. They create an event object and send that object to any registered listener. So far we ask, what is that event object? And what is a registered listener?

We start with the listener. Any listener in the Java community implements one of the listener interfaces available. So, a class promises that it will implement one or more interfaces and each of those implementations, the implemented methods, acts as a listener to certain event objects.

As with subscriptions, for example WarpCast news, a subscriber has to request e-mail news with the WarpCast server, else no e-mail will arrive. But after a subscription is successfully processed, each time a notice is posted it will arrive in your mail-box. Meanwhile you just sit and wait. In a similar way you have to add the listener object with the event source object.

That is, first you create the listener object implementing a suitable listener interface. Then you create an event source object, maybe a JButton, and add the action listener you created a moment ago to the subscription list of the event source object. After that the application will wait for user input, and when that happens an EventObject, or probably one of its subclasses, is created and sent to the listener objects at the list of this event source object. Mostly it is only one listener subscribed. The method catching the event object of the action performed will know what to do, that is the method you had to implement because of the promise made through the use of the interface. Often this method will be added to many different subscription lists and hence have to examine what to do, exactly as you maybe have subscribed to different mailing lists and probably have set the filter mechanism of your one e-mail client to handle them differently.

What are the EventObjects then? Quoted from the Java API: "All Event's are constructed with a reference to the object, the "source", that is logically deemed to be the object upon which the Event in question initially occurred upon." Yes, they are objects containing information that you might need whenever choosing what to do after the user input. For example, a MouseEvent object can give you the position of the mouse when a button was clicked, how many times it was clicked and upon which button of the common three mouse buttons. An ActionEvent from a JButton merely know which button was triggered and if any of the modifier keys were held down during this action event.

Let us add to the code we started out with. We will add one button and see what else is necessary then.

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class FirstButtonFrame extends JFrame implements ActionListener {
 
    private JPanel panel;
 
    /* the constructor of this class */
    public FirstButtonFrame() {
        /* JFrame methods */
        setTitle("FirstButtonFrame");
        setLocation(100, 50);
        setSize(250, 100);
 
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
 
        panel = new JPanel();
 
        JButton butt = new JButton("White");
        panel.add(butt);
        butt.addActionListener(this);
        butt.setActionCommand("Button 1");
 
        Container pane = getContentPane();
        pane.add(panel, "North");
    }
 
    /* merely the driver */
    public static void main(String[] args) {
         FirstButtonFrame frame = new FirstButtonFrame();
         frame.show();
    }
}

Since JButtons creates ActionEvent we states that we will implement the ActionListener interface. Please note that in the code above we have still not done that, we have not kept our promise to implement the interface yet. Please, try to compile the class now and you will get the most weird error message, obviously javac got lost and tells you what might be a reasonable conclusion. Anyway, javac tells you that the class 'does not define the method void actionPerformed(java.awt.event.ActionEvent) from interface java.awt.event.ActionListener', that is correct, we have not. Please hold on a moment, and let us look at the other new lines first.

We know that we will refer to the panel used to hold the buttons later on and thus declares the panel as a private class variable of JPanel type. Within the constructor we then instantiate the panel as a new JPanel.

Continuing with the button we create a JButton with the visible title "White". It will automatically be instantiated with the proper size and the given title. Because we never have to refer to the button later on we do not need to declare it as a class variable. It is not forbidden, but why declare class variables when we do not need to? That will only fill the class with scrawl, and make it hard to read. The panel will remember what is added to it, and that is enough.

Now the first step with event handling comes, adding an action listener. We have both an event source object, the JButton butt, and an object that promises to act as a listener, this time it is the context itself and hence we add this as the listening object.

The last line of the new lines might seem mysterious, butt.setActionCommand("Button 1"). In a later column we will discuss how to take powerful advantage of this feature, but for now we leave that with a short explanation; if no actionCommand is specified then JButton will use the text of the button as the actionCommand. But whenever you specifically set a command, that one will be used and remembered. We will look to that in a few moments.

The last two lines are not new to us, we simply add the panel to the contentPane of the frame.

The promise

We promised to implement the interface ActionListener and thus we will add a method for that. The method has to have the following signature since that is specified in the interface:

public void actionPerformed(ActionEvent e)

In fact, the only thing we might change is the name of the parameter variable, if it is a lengthy method we will make, you might chose a longer variable name, like evt or event. But except the parameter name, every letter have to be untouched. The code will look like

    public void actionPerformed(ActionEvent evt) {
        String cmd = evt.getActionCommand();
 
        System.out.print(cmd + "\t"); // writes cmd and a tab
 
        if (cmd.equals("Button 1")) {
            // doButtonOne(); <=== has to be added, too
        } else {
            System.out.println("Any error.");
        }
    }

Now you may compile the code and it works, but not much happens since we commented out the doButtonOne() method call. Anyway there is some output to the terminal window telling us "Button 1", so something is going on. The connection was, we made an object of the class and told it to show. Within the constructor block - constructors can be really long and nasty - we created a button object and added the class object as an action listener. Thereafter, any time you press the button an ActionEvent object is created and sent to the listener that loyally implemented the actionPerformed method, which take care of that object and simply asks it for the actionCommand we set to the button.

Since the actionCommand is always a text string we easily can test it against other text strings, but recall we have to make use of the method equals, since the two text strings certainly are not the same object and hence the == test will not work. We merely print the action command string and then do a test. Let us add the doButtonOne method after the actionPerformed code.

   private void doButtonOne() {
       System.out.println("is \"White\".");
       panel.setBackground(Color.white);
   }

To prohibit illegal calls to this method we hide it using private and it will be visible only within the surrounding object. The method simply prints a small message, an extension to the former print made in the actionPerformed code. After that the panel background is set to white. Please, remember to the remove the comment marks // from the actionPerformed code, as well as the trailing comment at that line.

You might think that it is not necessary to make special methods for the actions taking place within doButtonOne(), and you are right of course. Only two lines do not justify a method of their own, so simply view this as an example code. It is, on the contrary, most common with lengthy and complex actions taking place after a user input. Thus it is wise to get the habit of using helper methods right away. With wisely chosen method names the code will be easily read as well, 'if this is true then this will happen, aha!'.

The next step will of course be to add another button. The final code will look like this

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class FirstButtonFrame extends JFrame implements ActionListener {
 
    private JPanel panel;
 
    /* the constructor of this class */
    public FirstButtonFrame() {
        /* JFrame methods */
        setTitle("FirstButtonFrame");
        setLocation(100, 50);
        setSize(250, 100);
 
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
 
        panel = new JPanel();
 
        JButton butt = new JButton("White");
        panel.add(butt);
        butt.addActionListener(this);
        butt.setActionCommand("Button 1");
 
        butt = new JButton("Cyan");
        panel.add(butt);
        butt.addActionListener(this);
        butt.setActionCommand("Button 2");
 
        Container pane = getContentPane();
        pane.add(panel, "North");
    }
 
    public void actionPerformed(ActionEvent evt) {
        String cmd = evt.getActionCommand();
 
        System.out.print(cmd + "\t"); // writes cmd and a tab
 
        if (cmd.equals("Button 1")) {
            doButtonOne();
        } else if (cmd.equals("Button 2")) {
            doButtonTwo();
        } else {
            System.out.println("Any error.");
        }
    }
 
    private void doButtonOne() {
        System.out.println("is \"White\".");
        panel.setBackground(Color.white);
    }
 
    private void doButtonTwo() {
        System.out.println("is \"Cyan\".");
        panel.setBackground(Color.cyan);
    }
 
    /* merely the driver */
    public static void main(String[] args) {
         FirstButtonFrame frame = new FirstButtonFrame();
         frame.show();
    }
}

The only peculiar thing with the code added is that we reuse the local variable name butt. That is OK since we do not like to hold references to any of the buttons. In fact, as soon as the constructor block is finished the local name butt will disappear and no longer exist. The panel holds the buttons and will remember their existence, but not their former and temporary names. If this coding style annoys you, you might use a new local variable name each new item created, but with several buttons or other items that seems to be a tedious work.

Of course there are other small and new things in the code. An example of new things might be the \" that causes Java to print a quotation mark". But if there is anything, please use the forum and ask the question. I will answer any question I am able to answer about the Java columns.

Summary

Today we have looked at anonymity, and not only at anonymous inner classes but other minor objects, too. We have not used any inner class that we made ourselves but we have touched the idea though.

The main part of today's column was the event model, and if this seemed much to learn, stay rested. We will return to this topic many times and since we will continue with GUI programming we will discuss it over and over again. Anyway, you have to

  1. Make a listener object, that implements a listener interface
  2. Make an event source object, that creates event objects when triggered, and add the listener to it
  3. Catch the event objects in a properly implemented method, maybe examine the message it conveys

Now I will leave town and go fishing, go pick some berries or mushrooms and enjoy the wonderful creation found in the nature. See you next month.

The FirstButtonFrame.java