Previous |
Next |
In early versions of Java the graphical interface was implemented using a set of libraries called the AWT. AWT was designed to use the “native” widgets or controls on each supported operating system. The problem with this is that it meant that a widget could only be supported if it was present on all platforms. So if one operating system did not support a combo box (a combination of text box and list box) none of them could. In addition this “lowest common denominator” meant that AWT applications looked equally bad on every supported platforms. So whilst users of th e Apple Macintosh were used to using very visually appealing programs, perhaps verging on the beautiful. As soon as they ran a Java AWT application they were looking at an interface that was one step up from a text based screen.
To get around some of these limitations Sun developed a replacement for AWT called Swing. The Swing system has more controls, a better appearance and what is known as a Pluggable Look and Feel (or PLAF). By virtue of this, a program on the Macintosh actually looks like a Macintosh program, and a Windows program looks like a Windows program. With a single change in a line of code you can turn a program from one Look and Feel to another.
UIManager.setLookAndFeel(new com.sun.java.swing.plaf.windows.WindowsLookAndFeel());
//UIManager.setLookAndFeel(new com.sun.java.swing.plaf.motif.MotifLookAndFeel()); //UIManager.setLookAndFeel(new com.sun.java.swing.plaf.metal.MetalLookAndFeel());
|
|
The Pluggable Look and Feel of Swing allows a Java application to have the appearance of the native Operating System |
Whichever line is uncommented, the program will take on the Look and Feel. Thus the following to images are the same code except one is using the Motif, one the Windows look and one the Metal. (You can only run the Macintosh look and feel on Macintosh hardware due to the litigious nature of the Apple Computer company).



|
|
Exercise PlafPlay |
Find the SwingSet2.jar file in your JDK installation. This will be in a directory something like
C:\Program Files\Java\jdk1.6.0\demo\jfc\SwingSet2
Double click on the SwingSet2.jar and the demonstration application should start up. Select the Look and Feel menu option and switch between the different Look and Feel options. Note that the demo only supplies three but there are several others in existence.
Now locate the Metalworks demo program. This should be in a directory something like
C:\Program Files\Java\jdk1.6.0\demo\jfc\Metalworks
Double click on Metalworks.jar
I will only mention SWT in passing so you know what it is, rather than explain how to use it. Although Swing is generally a big improvement on AWT it has been criticised for performance issues. Engineers at IBM decided that they could do better than this and came up with the Standard Widget Toolkit, which like AWT used the widgets in the underlying platform. Unlike AWT however rather than take a “lowest common denominator” approach and give an interface that looks the same on each platform, SWT adopts the look of the native platform, and offers good performance. You can see SWT in action in the eclipse project (http://www.eclipse.org). In my view SWT is interesting but is not the standard in Java programming and unlikely to become the standard, so unless I have a very compelling reason to look further into it I am happy to leave it to the engineers behind the excellent eclipse development tool.
In the early days of Java it was assumed that its main area of success would be in Applets, small programs that get executed within the browser rather than on the web server. For various reasons applets have turned out to be a minority sport on the web. They suffered from performance and compatibility problems. Much of the compatibility issues stem from the different implementations from Microsoft, Netscape and Sun. Microsoft has never supported the Swing libraries and Netscape was late to support them. It was also found that few web sites actually needed to have code execute within the browser and where it was needed the needs were fairly trivial and would execute more quickly using a scripting language such as JavaScript (almost no relation to Java at all). It is hard to pursuade inexperienced users to download a 5 megabyte install program simply to get some feature working on your website unless they have a very pressing need for that feature. Many website designers have decided that Flash offers most of the programming features of applets but with better performance and wildly better control over appearance.
Under windows, when you access an applet the Java Plugin icon will appear in your system tray in a similar way to the following screen shot (the arrow points to the icon)
There are areas where nothing but an Applet will address the problem and the lack of compatibility across browsers was a thorny problem. As a result there was a minor industry in programming AWT applets that took account of the quirks between the Netscape/Microsoft/Sun implementations of Java. This ridiculous lack of standards was significantly addressed by Suns Java plugin. This is a kind of bridging technology that allows Applets to run using the standard Java runtime shipped by Sun in almost any browser.
|
|
The Java plugin gives a standard JVM target across all the major browsers. |
![]()
The plugin will run in both the Firefox and Microsoft browsers and gives programmers a single platform as a target for their programs. I
The idea of event handling is most commonly seen when a user clicks on something in a graphical application or hits a key. Java Event handling is based around the concept of event Listeners. A listener is created and attached to a component. The two main methods of creating listeners are
interfaces
adapter classes
Event handling involves the idea of interfaces, which use the keyword implements. You can think of using an interface as a little like the extends keyword with classes. Interfaces are a little strange in that they just control what methods you need to implement in your class.
The ActionListener interface is slightly different from most other event handling and its very useful for dealing with things like button clicks. The ActionListener only requires that you implement one method, called actionPerformed. For this demonstration I will create a separate class within the same file and use that class to handle the event. This example is rather brainless as it just outputs a number to the console, in a real application you would want to do something more graphical.
/**
Marcus Green 2007
using ActionListener to
handle events
**/
import java.awt.event.*;
import javax.swing.*;
public class ButtonClick extends JFrame {
JButton button;
public static void main(String argv[]){
ButtonClick bc = new ButtonClick();
bc.go();
}
public void go(){
button = new JButton("Click Me");
ButtonListener bl = new ButtonListener();
button.addActionListener(bl);
add(button);
setSize(100,100);
setVisible(true);
}
}
class ButtonListener implements ActionListener {
int clickCount;
public void actionPerformed(ActionEvent e) {
clickCount++;
System.out.println(clickCount);
}
}
|
|
Exercise: LoginRead |
This exercise involves modifying your Login application from chapter 1.5, so that it has a button that when clicked reads the contents of the name and password field. You can base your code on the following example.
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
public class Login extends JFrame {
JLabel lblName;
JTextField txtName;
JButton btnLogin;
public static void main(String argv[]){
Login l = new Login();
l.go();
}
public void go(){
lblName = new JLabel("Name");
txtName = new JTextField(8);
btnLogin = new JButton("Login");
setLayout(new FlowLayout());
add(lblName);
add(txtName);
add(btnLogin);
setSize(100,100);
setVisible(true);
}
}Create listener code so that when the button is clicked it outputs the contents of the name and password fields to the console.
Once you have that working add in a JPasswordField component and initialize it to a reasonable size (in the similar way to the 8 parameter to JTextField. Add code into your click handling so that the value in the password field is output to the console. Note, the method to get the content of a JTextField is getText and the method for getting the content of a JPasswordField is getPassword.
A single instance of a Listener class can be added to multiple components. This raises the question of how can you identify what component has generated the event. The solution is in the ActionEvent object that is passed to the actionPerformed method. The ActionEvent object is a little source of information about what has happened.
|
|
A single Listener class can be attached to multiple components. |
By calling the getActionCommand method of ActionEvent you can see what component generated the event. The following code attaches the same listener to two buttons and when either button is clicked it outputs either One or Two to the console.
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
public class MultiListen extends JFrame {
JButton btnOne;
JButton btnTwo;
public static void main(String argv[]){
MultiListen ml = new MultiListen();
ml.go();
}
public void go(){
btnOne = new JButton("One");
btnTwo = new JButton("Two");
ButtonListener bl = new ButtonListener();
btnOne.addActionListener(bl);
btnTwo.addActionListener(bl);
setLayout(new FlowLayout());
add(btnOne);
add(btnTwo);
setSize(100,100);
setVisible(true);
}
}
class ButtonListener implements ActionListener {
int clickCount;
public void actionPerformed(ActionEvent e) {
/** The magic **/
System.out.println(e.getActionCommand());
}
}
|
|
Exercise: MiniCalc |
Create an application called MiniCalc that has nine buttons labeled 1 to 9. Add two more buttons one with a + symbol and one with an = symbol. Your application should look something like the following.
Create a listener class (that extends ActionListener). Create a field to store a running total. In the actionPerformed method check if the + button has been pressed output the running total If it has not been pressed get the number and add it to a running total. Remember when comparing Strings you must use the equals method. You can get the primitive int value from a string that represents a number using new Integer(numbername).intValue();
If you found that easy, see if you can make it behave more like a real calculator.

When a class implements an interface it is contracting to implement the body in every method in the interface. So if you wanted to manage a window and used the WindowListener interface you would have to create a body for all 7 of the methods in that interface. If you were simply creating some test programs you might only want to actually process one of the events, that match the methods, and thus only need to create useful code for that methods. Despite only wanting to process one method, you would have to create an empty body for the other 6 methods. The adapter class helps get around this problem by supplying empty bodies for all the methods, and you then override the method that matches the action you want to process. If that explanation seems a little complicated, it is safe not to worry about it for the moment, and come back to it later.
The adapter class approach is slightly simpler than the interface approach so I will only cover that for the moment. Here is a modified version of HelloWorld that includes an adapter class that allows you to close down the Frame gracefully without resorting to the two finger salute, or Ctrl-c.
/* ShutHello */
// A Single line comment
import javax.swing.*;
import java.awt.event.*;//Note that handling is an awt class
public class ShutHello extends JFrame{
public static void main(String argv[]){
ShutHello shuthello = new ShutHello();
shuthello.go();
}
public void go(){
//Create an instance of the Adapter class
WindowCloser wc = new WindowCloser();
//attach that class to the current class
addWindowListener(wc);
JButton button = new JButton("Hello");
getContentPane().add(button);
setSize(100,100);
setVisible(true);
}
}
class WindowCloser extends WindowAdapter{
//override one of the methods in the Adapter class
public void windowClosing(WindowEvent e){
System.exit(0);
}
}The event handling code
WindowCloser wc = new WindowCloser();
//Attach that listener to this program
addWindowListener(wc);
The first line creates an instance of the WindowCloser class (explained a little later here). The next line attaches this class as a listener to the current instance of the program. This line has an implicit reference to the this instance. Thus it would also correct to have this line as
this.addWindowListener(wc);
If the WindowCloser class were correctly defined outside this file, this would be all you would have to do to implement code to close this window. However, in this instance the WindowCloser class is actually defined within the same file and is explained next.
class WindowCloser extends WindowAdapter{This line defines a new class within the current file. The name WindowCloser is arbitrary but I have chosen it to indicate the purpose of the class. It extends WindowAdapter which is a class that offers methods that control the sort of events that might happen to a window.
public void windowClosing(WindowEvent e){
System.exit(0);
}These lines override the windowClosing method in the WindowAdapter class. Note the naming convention where the method name starts with a lower case letter. This is in contrast with the name of the parameter that starts with an upper case letter. When learning the methods it is easy to get this convention wrong and wonder why the code will compile but not do what you expect. With luck you will mainly use a GUI builder such as NetBeans to actually create this sort of code.
The System.exit(0) line simply halts the running of the current program. It would be possible to write code to close the current window, but stopping the current program is easy to do and has the effect of closing the window. This line that shuts down the program is where the real work is done. The rest of the code is mainly window dressing. There are a limited number of events that can be trapped and it is what you do with them that counts. Thus for instance you might attach an event to a button that opens another frame and initialises some values on that frame according to the contents of a text field.
If you use a GUI builder such as NetBeans you will soon notice if you look at the code that it does not produce external classes for the event handling code as I have but uses the concept of inner classes. Where I have created the WindowCloser class as an external class within the same file, NetBeans creates an instance of the class actually within the event handling method. This is very handy for a GUI builder tool and keeps the code compact but it is more complex to write by hand as you have to keep a close watch on opening and closing of parenthesis and curly braces. The actual principal of using Listeners is identical.
Other sources
Using Action Listeners according to
Sun
http://java.sun.com/docs/books/tutorial/uiswing/events/actionlistener.html
Previous |
Next |