THE JAVA FOUNDATION CLASSES
( J F C )


The problem with all mothers is that they love to boast about their new babies to the entire world. Oh, what a sweet child I have ! At such a tender age, my child can do so many things! No other baby is as good looking as my own! And they would go on and on. It was the same story when, about two years ago Sun Microsystems told us about their new baby, whom they had named Java. Java, they told us, was better than anything, anyone in the software industry had ever produced. The things it could do were absolutely incredible. Why, it could even work on any platform! Have you ever heard of anything like it before? Write a program once and it would work anywhere. And ofcourse, nothing looked as beautiful as Java.

We were hooked! We had heard other mothers boast about their babies but this seemed different. We fell in love with Sun's baby for the promise it held of ushering a new paradigm in the world of Information technology. That promise, alas, remained just a promise. Our relationship with Java turned into one with many ups and downs, with more downs than ups. Simply because we realised there really wasn't a lot that we could do with Java. And as far as the looks department was concerned, well, Cindy Crawford wasn't about to feel threatened by Java. And that's probably one hell of an understatement. Because we actually thought that the output we got from Java looked quite ordinary. We felt let down.

But all that was before the Java Foundation Classes or the JFCs were released. When we first heard Sun talk about the JFCs, we wondered whether the people at Sun were referring to Jokes For Crossplatform workability. To tell you the truth, earlier, we had been so disappointed with Java that we defected to MicroSoft's ActiveX. We spent more than a year going ga-ga about the brilliant features of ActiveX. It not only looked good but also could actually do really great things. No longer. We are back home to where we belong. With Java. Infact, had Java been like this since the beginning, we would have never gone astray.

So let's move onto looking at a couple of programs in the JFCs. We hope that you will be convinced that this is definitely where our world is going to be heading.

program 0
zzz.java

import java.applet.*;
import java.awt.*;
public class zzz extends Applet
{
public void init()
{
  Button b;
  b = new Button("Hi");
  add (b);		
}
}

If you do not understand this program, then please refer to our earlier Java tutorial . We compile this program using javac and run it using Appletviewer. All that this program does is place a Button on our screen,which says 'Hi', when we view it through Appletviewer. This is the type of output we get when we use the original JDK1.0. Not very impressive. Which is why we called this program 0. Another word for useless or dull. Time to get to the real thing.

zzz.java

import java.applet.*;
import java.awt.*;
public class zzz extends Applet
{
public void init()
{
      JButton b;
      b = new JButton("Hi");
      add (b);		
}
}

In our first program, we have merely added a 'J' in front of Button to get the term JButton. Now when we say 'JButton b; ', we are merely informing the compiler that b looks like a JButton. Which means that it has all the properties and attributes of a JButton. We haven't as yet created a JButton in our program. To do that, we have to actually say that b=new JButton() or call a function that returns an object that looks like a JButton. When we compile this program using the javac compiler, we get an error message that says 'class JButton not found in type declaration'.

There's a simple reason for this error. If you told me on the phone that your name is Bill, I wouldn't know who you were. Bill Clinton? Bill Gates? Billy The Kid? I wouldn't know.Until you told me your full name. I'd probably slam the phone down,anyway. But don't get depressed so soon. Precisely, what the compiler is doing right now is saying 'give me your full name or else how am I to know who you are?'. Well the full name of JButton is com.sun.java.swing.JButton. Write this full name and the compiler should be able to recognize you. However an easier method of doing things is to write the statement

 import com.sun.java.swing.*; 

The terms after the word 'import' and before the '*' will automatically become a prefix to JButton whenever needed. This is shown in the next program .

zzz.java

import java.applet.*;
import java.awt.*;
import com.sun.java.swing.*;
public class zzz extends Applet
{
public void init()
{
      JButton b;
      b = new JButton("Hi");
       add (b);		
}
}

When we compile this program we once again get errors. This is because when we use an import statement, the java compiler by default looks into classes.zip in the Java\Lib directory. The Java Foundation Classes works with JDK1.1.2 onwards and right now we are working with JDK1.1.3. We have to get our compiler to look at two other files namely rose.jar and swing.jar in addition to classes.zip. This is because running a java applet requires a few class files, a few gif files and other things. Now to call these files one at a time slows down java. That's why we put everything we require into a single file which our compiler can now look at in one go. Maybe, the grandmother of someone at Sun used to put a lot of goodies in a jar. That's probably why a collection of classfiles , gif files and other things for an applet to run is called a jar file. The compiler will look at these files when we set our classpath to point to these files. For this we use the statement

 set classpath =c:\swing-0.2\swing.jar;c:\swing-0.2\rose.jar;%classpath%

The %classpath% will append our original classpath to this classpath. Now compile this program again and run it. What do you see? Same old ugly button. You mean we went through that much trouble just to get something that looked as bad as the best that JDK1.0 could offer. Oh no! That's why we ran away from java in the first place! And what about all those terms we kept on hearing about like ModelViewController, delegates,etc? Things that were supposed to make java better looking?

Relax. In case you are wondering whether to go further in this tutorial, let me assure you that we shall get to all those terms at a relaxed pace. You probably won't even realise that we have run programs using 'delegates', 'MVC',etc , until we actually point out to you that you have. And we solemnly promise to create better looking buttons in the future.

zzz.java

import java.applet.*;
import java.awt.*;
import com.sun.java.swing.*;
public class zzz extends Applet
{
public void init()
{
      JButton b;
      ImageGlyph  i;
      i = new ImageGlyph("buttonImage3.gif");	
      b = new JButton(i);
       add (b);		
}
}

Before you run this program go to swing-0.2\examples\swingset\images and copy all the 'gif' files into your current directory. A gif file merely contains an image. In this program we have the term ImageGlyph. ImageGlyph is an object that stands for an image. We can use any gif file but right now we are using the files that Sun has given us. When we run this program, we see a button resembling a round circle with a bright green arrow in the centre. If you had worked with java earlier, you would have realised that this button looks a lot better than what buttons used to look like. And all that we have done is to create an ImageGlyph using our gif file and adding this ImageGlyph to our button. The image contained in buttonImage3.gif file gets pasted on to our button. Earlier when we used button, all we could do was to add text to it. Now in addition to plain text ,we can also add images to our buttons. In the good old days, if we wanted to paste on images using java all we could do was to sit on our heads in some yoga style and meditate, waiting for the JFCs to be released. In fact, if you were into all that, my friend Vivek knew a couple of people who had claimed to have attained Nirvana or Supreme Enlightenment that way. Unfortunately, none of them were ever named Kurt Cobain. But, right now, we can stop meditating because the JFCs are here, and we have work to do. Later on we shall be comparing JFCs with the MFCs. At that point , you would realise that there's probably no easier way to paste an image onto the a button than when using the JFCs. That's also one of the major reasons why we have come back to Java. It's so simple to learn and work with.

zzz.java

import java.applet.*;
import java.awt.*;
import com.sun.java.swing.*;
public class zzz extends Applet
{
public void init()
{
      JButton b;
      ImageGlyph  i , j;
      i = new ImageGlyph ("buttonImage3.gif");	
      j = new ImageGlyph ("duke.gif");	
      b = new JButton (i);
      b.setPressedGlyph (j);
       add (b);		
}
}

In this program, we have created two ImageGlyphs. The only thing new in this program is the line b.setPressedGlyph(j). Here, we obviously mean that 'setPressedGlyph' is a function in JButton. When we run our program, we see our image, namely 'buttonImage3.gif' on our button, as in our previous program. Now, due to this statement, when we keep the mouse depressed on the our button, the first image is replaced by the second. So as long as we keep the mouse depressed, we see the image of a duke with a funny hat. When we release the mouse, we once again see our original image, that is in buttonImage3.gif.

Just a word of caution
Earlier on, before the Internet really took off, we used to have alpha, beta and final versions. In the alpha versions, out of ten promised features,three would probably work. In beta versions, around seven of these features would work. And in the final versions, no one knew how many features would or would not work. What we are working on, is a Preview version. So, if you run any of these programs six months down the line and something doesn't work, don't blame us, because these specifications are subject to change.

zzz.java

import java.applet.*;
import java.awt.*;
import com.sun.java.swing.*;
public class zzz extends Applet
{
public void init()
{
  JButton b;
   ImageGlyph  i , j;
   i = new ImageGlyph ("buttonImage3.gif");	
    j = new ImageGlyph ("duke.gif");	
    b = new JButton (i);
    b.setRolloverGlyph (j);
     add (b);		
}
}

This program is similar to the previous program, where we have two ImageGlyphs and want to replace one with the other. By now, however, we must have become pretty lazy. I mean, why take all the trouble to click on our JButton and keep it depressed to change the image, when we can achieve our objective by merely positioning the mouse over our JButton? Fortunately, we have some thing just for you . Something called setRolloverGlyph( ) . So execute this program and just place the mouse over the Button. You will notice the change immediately. The first image has been replaced by the second. Move the mouse away from our JButton, and once again, we see the original image.

A point to be remembered here is that when we say b.setRolloverGlyph( ) ,we obviously mean that the function setRolloverGlyph is part of JButton. This may, however, not be the case, as JButton itself may be derived from something else which contains this particular function. Don't worry about this right now, as we shall be covering all this in greater detail later on.

zzz.java

import java.applet.*;
import java.awt.*;
import com.sun.java.swing.*;
public class zzz extends Applet
{
public void init()
{
     JButton b;
      ImageGlyph  i , j;
      i = new ImageGlyph ("buttonImage3.gif");	
      j = new ImageGlyph ("duke.gif");	
      b = new JButton (i);
      b.setEnabled (false);
      b.setDisabledGlyph (j);
       add (b);		
}
}

In Java, most components, like JButtons, JCheckboxes,etc are all derived from the class, JComponent. They therefore, can make use of all the functions of JComponent. One of these is the function setEnabled(). This function requires a boolean as a parameter. When we say b.setEnabled(false), all that we are doing is disabling b, which is our JButton. The next line b.setDisabledGlyph(j) simply says that when b has been disabled, replace the first ImageGlyph with the one in 'j'. When we execute this program, we don't see the first image at all, as the button has been disabled immediately on execution. We directly get to see the second image.

zzz.java

import java.applet.*;
import java.awt.*;
import com.sun.java.swing.*;
public class zzz extends Applet
{
public void init()
{
      JButton b;
      b = new JButton ("Hello");
      Font f=new Font ("Dialog",Font.BOLD,24);	
      b.setFont (f);
       add (b);		
}
}

Maybe, we do not like the look of the text that we have placed in our JButton. Or maybe we just want to increase the size of the text to make it more prominent. All we have to do is to change the font. We first create an object that looks like a Font. While doing this, we have to give it three parameters. The first is the name of the font. The second refers to the properties of the font, that is, whether the font is bold, italic, or underline or strikethrough. And finally we give the point size. We should know that 72 points make an inch. JButton has a function setFont( ) to set a particular font for what ever we have written.

zzz.java

import java.applet.*;
import java.awt.*;
import com.sun.java.swing.*;
public class zzz extends Applet
{
public void init()
{
     JButton b;
      b = new JButton ("Hello");
      b.add(Box.createRigidArea(new Dimension (100,50)));
      add (b);		
}
}
	

Sometimes, we might have too many buttons on a screen and they might appear too close to each other. To avoid any cluttering of buttons, we need to separate our buttons. Box is a static object. It has a static function called createRigidArea ( ). Due to this function, our JButton will now be allocated some area on the screen. Of course, we still have to specify how large we want this area to be. For this, we have to pass a Dimension function to it, which contains the width and the the height . Once we have created this area around our box, nothing else besides our JButton can occupy this area. Any new component will now be placed outside this area.

zzz.java

import java.applet.*;
import java.awt.*;
import com.sun.java.swing.*;
public class zzz extends Applet
{
public void init()
{
   JCheckBox b;
    ImageGlyph a = new ImageGlyph ("buttonImage3.gif");
    b = new JCheckBox(a);	
    add (b);		
}
}

Now that we have done JButtons, we shall realize that JCheckboxes are almost exactly the same thing,except for the fact that the borders around a checkbox aren't clearly visible. Compared to earlier Checkboxes in Java, we can now add an ImageGlyph to our JCheckboxes.

zzz.java

import java.applet.*;
import java.awt.*;
import java. awt.event.*;
import com.sun.java.swing.*;
public class zzz extends Applet
{
public void init()
{
   JCheckBox b;
   ImageGlyph a = new ImageGlyph ("buttonImage3.gif");
   b = new JCheckBox(a);	
   b.addItemListener (this);
    add (b);		
}
}

It is not sufficient to merely place a checkbox on our screen. When we click on our checkbox, we want to know if we have actually clicked or not. We may find out whether we have clicked by making use of the function addItemListener (), within which we pass the parameter 'this'. When we compile our program, we get some strange error message that says 'Incompatible type for method. Explicit cast needed...'. The parameter 'this' refers to our current object. In our case, the current object is zzz as well as Applet. But the function addItemListener demands that it requires an object that is an ItemListener. This is now shown in the next program.

zzz.java

import java.applet.*;
import java.awt.*;
import java.awt.event.*; 
import com.sun.java.swing.*;
public class zzz extends Applet implements ItemListener
{
public void init()
{
     JCheckBox b;
      ImageGlyph a = new ImageGlyph ("buttonImage3.gif");
      b = new JCheckBox(a);	
      b.addItemListener(this);	
      add (b);		
}
}

In this program we have to make sure that our current object is an ItemListener. Remember that a class cannot extend more than one base class at a time. We have now used the term 'implements' to append ItemListener to our class. Now 'this' in addItemListener( ) refers to zzz, Applet as well as ItemListener. On compilation, we still get an error which tells us that we do not have some abstract function. This is because when we say 'implements ', we can be sure that whatever follows this term is an Interface. Within an Interface, all the functions are Virtual functions. These functions do not contain any code. To remove the errors in our program, all we have to do is to add these functions to the class that implements the interface. When we say our class extends another class, we mean that our class contains all the code that was present in the base class, but when we say that our class implements an interface, it means that our class will now contain all the functions that are present in the interface. The interface in our program, namely ItemListener, has only one virtual function 'itemStateChanged( )', which we have added in our next program.

zzz.java

import java.applet.*;
import java.awt.*;
import java.awt.event.*; 
import com.sun.java.swing.*;
public class zzz extends Applet implements ItemListener
{
public void init()
{
   JCheckBox b;
   ImageGlyph a = new ImageGlyph ("buttonImage3.gif");
   b = new JCheckBox(a);
    b.addItemListener(this);	
   add (b);		
}
public void itemStateChanged(ItemEvent e)
{
   System.out.println("function called");
}
}

When we now compile the program all the errors disappear, confirming that there is only one virtual function in ItemListener. As we said earlier, the only prerequisite is that the function must be present within our class. Within this function, we may add any code that we may want. Here, we have placed the statement System.out.println( ). When this function gets executed, whatever text we have written within the function appears at our DOS prompt, for the number of times that we have clicked on our JCheckbox. System, by the way, is a static object. What we mean by that term is that we don't have to say 'new' to make use of it. At this point, we must realise that we may have more than one checkbox in our program, which may also call itemStateChanged. To distinguish between different components calling this function,we use ItemEvent. We also note that addItemListener is one of the new concepts of jdk1.1. Earlier, when we wanted to call a function we had to use handleEvent. Here, things have been made much simpler, as we can now call our own code.

zzz.java

import java.applet.*;
import java.awt.*;
import java.awt.event.*; 
import com.sun.java.swing.*;
public class zzz extends Applet implements ActionListener
{
public void init()
{
   JButton b;
   ImageGlyph a = new ImageGlyph ("buttonImage3.gif");
   b = new JButton(a);
    b.addActionListener(this);	
    add (b);		
}
public void actionPerformed(ActionEvent e)
{
   System.out.println("function called");
}
}

An ItemListener is essentially meant for a JCheckbox. When we are working with buttons, we would rather use an Action Listener. This Interface, as well, has only one virtual function which we have to add within our class which implements ActionListener. This function is called actionPerformed. Also we use ActionEvent to distinguish between different JButtons. Now every time we click on JButton, our code which is in actionPerformed gets called. This is how we handle events in the Java Foundation Classes.

zzz.java

import java.applet.*;
import java.awt.*;
import com.sun.java.swing.*;
public class zzz extends Applet
{
public void init()
{
     JLabel l=new JLabel("hi");
     add( l);
}
}
	

If we want to print any text on to our screen, we normally make use of a label. The size of the label will vary according to the size of the text we have placed into it. Here, we have only written the word 'hi'. Short and sweet. This now appears at the top of our applet in the centre.

zzz.java

import java.applet.*;
import java.awt.*;
import com.sun.java.swing.*;
public class zzz extends Applet
{
public void init()
{
     ImageGlyph i=new ImageGlyph("duke.gif");
     JLabel l=new JLabel("hi");
     l.setGlyph( i);	
     add( l);
}
}

A JLabel, as with everything else in the JFCs, can have two entities within it. What we mean to say is that within a JLabel, we can have an image as well as some text, both of which may be independent of each other. Here, when we created our JLabel, we associated a text 'hi' with it. We also create an ImageGlyph. Every JLabel has a function setGlyph( ). We place our Image Glyph within this function. When we execute this program, our label now contains an image as well as the text, side by side.

zzz.java

import java.applet.*;
import java.awt.*;
import com.sun.java.swing.*;
import com.sun.java.swing.text.*;	
public class zzz extends Applet
{
public void init()
 {
      setLayout(new BorderLayout());
      ImageGlyph i = new ImageGlyph ("BigTiger.gif");
      JLabel l=new JLabel(i);
      add(l);
}
}

In this program, we have created an ImageGlyph as we had done earlier. We have added this ImageGlyph to a JLabel. This JLabel has now been added to our screen. We have also created the simplest of borders for our applet when we said setLayout(new BorderLayout( )). The difference, in this program, is that the image we have in our gif file is of a size much larger than any image that we have used before. When we run this program, if we get the feeling that we aren't really getting to see the entire image, we might probably just be right. Even if we increase the size of our applet to it's full size, we may still not see the full image. After all, the image in this gif is probably larger than even our entire screen. Wouldn't it be great if we could just scroll through the image, just as we use a scrollbar to view a large text document ? Well, we are trying to do just that in our next program.

zzz.java

import java.applet.*;
import java.awt.*;
import com.sun.java.swing.*;
import com.sun.java.swing.text.*;	
public class zzz extends Applet 
{
public void init()
 {
      setLayout(new BorderLayout());
      add("Center",new yyy());
}
}
class yyy extends JScrollPane
{
public yyy()
{
      ImageGlyph i = new ImageGlyph ("BigTiger.gif");
      JLabel l=new JLabel(i);
      add(1);
}
}

We know that one class can not extend more than a single base class. To overcome this difficulty, we create another class which can now extend the particular class that we require, namely JScrollPane. JScrollPane contains functions that will enable us to create scrollbars within our Applet. We call the constructor of this class when we say new yyy( ), from init( ). However, when we now run this program, we find that only the border has been formed within our applet. We don't get any image unlike in one of the earlier programs , here we at least got to see half the image. We rectify this problem in the next program.

zzz.java

import java.applet.*;
import java.awt.*;
import com.sun.java.swing.*;
import com.sun.java.swing.text.*;	
public class zzz extends Applet 
{
public void init()
 {
      setLayout(new BorderLayout());
      add("Center",new yyy());
}
}
class yyy extends JScrollPane
{
public yyy()
{
      ImageGlyph i = new ImageGlyph ("BigTiger.gif");
      JLabel l=new JLabel(i);
      getViewport().add(1);
}
}

All that we have done out here is to write getViewport( ).add( l ) instead of just add( l ). Here, we are saying that getViewport() is a function within JScrollPane which ensures that scrollbars appear within our applet when we call the function add() from it. When we have an image that is too large to fit onto our screen, we need to create a smaller window to enable us to view just a portion of the image. This is done by getViewport(). If we now use the scrollbar, we may see another part of the image. All this assumes that the image within our gif file is large enough, otherwise we shall not see any scrollbars.

zzz.java

import java.applet.*;
import java.awt.*;
import com.sun.java.swing.*;
public class zzz extends Applet
{
public void init()
 {
     ImageGlyph i=new ImageGlyph("dukeWave.gif");
     JLabel l=new JLabel("hi");
     l.setGlyph( i);	
     l.set HorizontalAlignment(l.RIGHT);
     l.set VerticalAlignment(l.TOP);
     l.set VerticalTextPosition(l.TOP);
     l.set HorizontalTextPosition(l.LEFT);
     l.setForeground(Color.green);
     add(l);
 }
}

In this program, we would like you to do a little experimentation. For all vertical positions of the JLabel, try replacing TOP by bottom or CENTER, while for the horizontal positions, we may experiment between LEFT , RIGHT and CENTER. A point to be noted is that you might not even the change in the position of the image within the JLabel, because the size of the label automatically varies with whats within it due to this, we may not notice much difference between say TOP and BOTTOM. But do try to shift the position of the text with respect to the image. For example, you could shift both text positions to the center and notice the change.

zzz.java

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;
public class zzz extends Applet implements ActionListener
{
 JProgressBar p;
 public void init()
 {
      JButton b;
      b=new JButton("click");
      p=new JProgressBar();	
      b.addActionListener(this);
      p.setMinimum( 0);
      p.setMaximum( 100);
      p.setValue( 10);
      add( b);
      add( p);
}
public void actionPerformed( ActionEvent e)
{
     int i=p.getValue()+10;
     p.setValue( i);
     System.out.println("hi");
}
}	            

Whenever software is in the process of being installed onto our computer, we see a progress bar which tells us how much of the process has been completed. The problem with most progressbars we have seen to date is that they are never accurate. Sometimes the pointer of the progress bar will move slowly in the beginning and then in a flash of a second, will reach the end. At other times, it moves quite fast, but stops just before the end of the bar for a time period that seems like infinity. Anyway, lets see how the Java Foundation Classes have implemented progressbars. We have added an ActionListener to the button in our program. The bare minimum information we need to give our progressbar are the values at the extreme left end and the extreme right end of the progressbar. For this we have two functions, setMinimum() and setMaximum() respectively in JProgressBar. The function setValue() tells the pointer of the progress bar where it should start from when it first starts executing. Here we have placed the initial position at 10 using this function. Whenever we click on the button, the current value of the progress bar is obtained by the function getValue(). We add 10 to this value, and place it in a variable i. The current value of the progressbar is now set to the the value in variable i. Thus each time we click on the button we increment the value of the progressbar by 10. When we click on the button for the first time, the initial value is10, which is now incremented by 10 to become 20. The pointer of the progressbar now points to this value. In a practical progressbar, we may use something else besides a button to cause the progressbar's pointer to increment by a fixed amount, but the concept remains the same.

zzz.java

import java.applet.*;
import java.awt.*;
import com.sun.java.swing.*;
public class zzz extends Applet 
{
public void init()
{
    setLayout(new BorderLayout());
    add("Center",new sss());
}
}
class sss extends JPanel
{
public sss()
{
     JSlider s;
     this.setLayout(new BorderLayout());	
     s=new JSlider(JSlider.HORIZONTAL,100,1000,400);
     s.setPaintTicks(true);
     s.setMajorTickSpacing(20);
     s.setBorder(new JTitledBorder(s,"MajorTicks"));
     this.add(s);
}
}

If you look at any music system, you'll notice that you can adjust the volume or the base and other functions using a slider. A slider is normally used when we have a wide range of values and we want to choose a value within that range without typing in that value. When we have a sliderpanel, all we do is to move the slider to the required value. Earlier, it was almost impossible to obtain a slider in Java. In contrast, Windows95 allowed us to create a slider with great ease. Now, using the JFCs, this is possible in Java, as well. We first create an object that looks like a JSlider. We have specified that it's alignment is horizontal. As we had done earlier with our progressbar, we specify the minimum and maximum values of the slider, as well as the value we want it to be set at initially. If we just write only the first three lines within the constructor and then say add(s), we shall obtain a slider which we can drag with a mouse from one end to another. The only problem is that we shall have difficulty placing the slider at any particular value we want it at. For this, we enable markers between the two ends. We also specify how much space should be there between each marker, using the function setMajorTickSpacing(). Around our slider, we also want a border with some title. So, here, we have put a border that looks like JTitledBorder(), with two parameters: s refers to our slider around which we want our titled border and the second parameter now becomes the title of our slider. If we say this.add() or this.setLayout(new BorderLayout()), 'this' merely refers to the current class we are in. It doesn't make a difference if we do no write 'this' before add().

zzz.java

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;
public class zzz extends Applet 
{
public void init()
{
setLayout(new BorderLayout());
add("Center",new sss());
}
}
class sss extends JPanel implements ChangeListener
{
JLabel tf;	
public sss()
{
     JSlider s;
     setLayout(new BorderLayout());	
     tf=new JLabel("Slider value:  ");
     add("South",tf);
     s=new JSlider(JSlider.HORIZONTAL,100,1000,400);
     s.setPaintTicks(true);
     s.setMajorTickSpacing(20);
     s.setBorder(new JTitledBorder(s,"MajorTicks"));
     s.addChangeListener(this);	
     this.add(s);
}
public void stateChanged(ChangeEvent e)
{
JSlider s1 =(JSlider) e.getSource();
tf.setText("Slider Value: "+s1.getValue());
} 
}

It's not possible for us to be totally satisfied by merely moving the slider from one end to another. We would also like to know the current position of the slider. To do this , we have created another JLabel and placed it in the south. Now all user interface tools have a listener associated with them. A slider has a ChangeListener. Here we have written s.addChangeListener(). The 'this' merely specifies that ChangeListener which is an interface is in in the very same class. We have a function called StateChange within Change Listener which will get called each time we move the slider up and down. We have a parameter that looks like ChangeEvent that would allow us to distinguish between different sliders calling the function stateChanged (). But right now we have only one slider so that is not important. Here e.getSource will return the object that calls stateChanged(). In this case, we know that it is a JSlider, so that is what we are casting it to. The getValue() function will tell you the current position of the slider. Now setText() will allow this value to be seen on our label at runtime.

zzz.java

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;
public class zzz extends Applet 
{
  public void init()
   {
     setLayout(new BorderLayout());
     add("Center",new ttt());
   }	      
}
class ttt extends JPanel
{
public ttt()
{
setLayout(new BorderLayout());
TreeNode to=new TreeNode("music");
TreeNode ca;
TreeNode co;
TreeNode st;
ca=new TreeNode("classical");
to.add(ca);
ca.add(co=new TreeNode("Beethoven"));
co.add(st=new TreeNode("Concertos"));
st.add(new TreeNode("No. 1 - C Major"));
st.add(new TreeNode("No. 2 - B -Flat Major"));
JTree tr=new JTree(to);
add("Center",tr);
}
}	

If you run the programs like winfile or explorer, you will notice a very typical structure of the layout. If we click on the plus sign boxes in front of any of the directories, they open out to show the subdirectories. Similarly, clicking on the plus sign boxes in front of the subdirectories results in further subdirectories, or files being displayed. As soon as we click on the plus sign boxes to display whatever is in them, the plus sign boxes are replaced by minus sign boxes. Clicking on the minus sign boxes will now collapse the files. This is what we are trying to do in this program. Here, we create various objects that all look like TreeNode. Our first TreeNode object is called to and we have a text associated with this object that says 'music'. If we stop here and execute this program, we shall simply see this single node that says 'music'. While creating the object, ca, we have asociated the text 'classical' with it. This has been added to our first object, to. To the object, ca, we have added the object,co, which has the text 'Beethoven'. To the object, co, we have added the object,st, with the text 'Concertos'. To st, we have added two objects with the text 'No 1 - C Major' and 'No 2 - B - Flat Major'. Finally, we have created a JTree to which we have added our first TreeNode, namely to. We can now see our entire tree.

zzz.java

	
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;
import java.lang.*;
import com.sun.java.swing.table.*;
public class zzz extends Applet 
{
  public void init()
  {
	JButton b=new JButton("Hello, how are you");
	add(b);
	DebugGraphics.setFlashTime(10);
	b.setDebugGraphicsOptions(DebugGraphics.FLASH_OPTION);
  }
}

To deal with problems that we may encounter with any graphics application in java, we have a static object called DebugGraphics. This static object has a function called setFlashTime(). Our image will be drawn on screen within a time duration that depends on the value we pass to this function. In the next statement, we have said setDebugGraphicsOptions(DebugGraphics.FLASH_OPTION); where FLASH_OPTION is another static variable in DebugGraphics. Each time a paint message comes, this is the function that will cause our image to be redrawn. Since we are redrawing our image very slowly, we can see, at what point in time, any errors in the drawing of the image, occur. In this program, we have only used DebugGraphics to check whether a button is being drawn properly. But practically, it is used for debugging complicated objects on screen when we want to see in slow motion what is happening at every stage. We could try this function with another component, or a User Interface.

zzz.java

import java.awt.*;
import com.sun.java.swing.*;
public class zzz extends JPanel 
{
static JFrame frame;
public static void main(String s[ ])
{
frame = new JFrame("zzz");
frame.add("Center", new zzz());
frame.pack();
frame.setVisible(true);
}
}

We now get down to working with applications in java. When we run such an application, we don't use appletviewer, but instead say java zzz. All the programs that we shall be doing after this will be applications and not applets. In an application, the first function to be called is always main(). The reason that we have made main public is because we want every one to be able to access it. The function main() gets an array of strings, which are the parameters we may pass after the name of the program. We create a JFrame with the title zzz. In this frame, we put all things together using the function pack(). Without setVisible( true), we shall not be able to see anything. Notice that we have declared frame to be of type static JFrame. We have to declare it as static to be able to use it in another function, in this case main(). Alternately, we could have put this statement within the function main(), in which case, we may avoid the use of the term static.To learn more about applications in java, refer to our tutorial .

zzz.java

import java.applet.*;
import java.awt.*;
import com.sun.java.swing.*;
import com.sun.java.swing.text.*;	
public class zzz extends JPanel 
{
	public zzz()
	 {
		JRadioButton b;
		b=new JRadioButton("hello");
		b.setKeyAccelerator('o');	      
            add("Center",b);
	}
       public  static void main(String s[])
	{
		JFrame f = new JFrame("hi");
		f.add(new zzz());
		f.pack();
		f.setVisible(true);
	}
}
	

A radiobutton functions in a manner similar to that of an ordinary button or a checkbox, only it is smaller and round in appearance. Each and everyone of these components have a function setKeyAccelerator(). Now when we write o in single quotes within this function, and now execute this program, we shall notice that the first occurance of the letter we have placed within this function is now underlined. If we now press the Alt key as well as the letter o, our radio button which contains this text is activated. The function setKeyAccelerator() enables Sun to implement, in part, a very crucial concept of almost all computers used today. A concept that says that even if our mouse is not working properly, we must be able to operate our computer , using a keyboard. This is something of a standard across platforms and Sun has made it very clear that we shall be able to use the Java Foundation Classes using only a keyboard, without using a mouse. { Have you ever wondered what happens to a Mac user when his mouse is giving him problems ? Don't even ask ! It's probably just one among a million reasons why Macs will die a natural death.}

zzz.java

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;
import com.sun.java.swing.text.*;

public class zzz extends JPanel 
{
static JFrame frame;
public zzz()    
{
JMenuBar m = new JMenuBar();
JMenu f = new JMenu ("File");
f.setGlyph(new ImageGlyph("folder.gif"));
m.add(f);
m.validate();
add(m);
}
public static void main(String s[ ]) {
frame = new JFrame("zzz");
frame.add("Center", new zzz());
frame.pack();
frame.setVisible(true);
}
}

As we said earlier, the first function to be called in an application is main(). When we say new zzz(), we are calling the constructor of the function zzz. Here, we have created a menubar called m of type JMenuBar. Now to this menubar we are going to add our menus. Our first menu has been called f and has a text 'File' associated with it. Also in this menu, we have created an ImageGlyph, which we add to our menu. When we say validate(), what we are doing is forcing the menubar to redraw itself.

zzz.java

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;
import com.sun.java.swing.text.*;

public class zzz extends JPanel 
{
static JFrame frame;
public zzz()    
{
JMenuBar m = new JMenuBar();
JMenu f = new JMenu ("File");
f.setGlyph(new ImageGlyph("folder.gif"));
f.setHorizontalTextPosition(JButton.RIGHT);
m.add(f);

JMenu gg = new JMenu ("Color");
gg.setGlyph(new vvv(Color.red));
gg.setHorizontalTextPosition(JButton.RIGHT);
m.add(gg);

m.validate();
add(m);
}
public static void main(String s[ ])
{
frame = new JFrame("zzz");
frame.add("Center", new zzz());
frame.pack();
frame.setVisible(true);
}
}

class vvv implements Glyph
{
Color c;
vvv( Color r)
{
this.c = r;
}
public void paint(Graphics g,int x,int y)
{
Color o=g.getColor();
g.setColor(c);
g.fill3DRect(x,y,getWidth(),getHeight(),true);
g.setColor(o);
}
public int getWidth(){return 15;}
public int getHeight(){return 15;}
}

Now we have added one more menu, gg, to our menubar. We have a text associated with it called 'Color'. We, however, want to create our own image to be put along with this menu instead of using a readymade gif file. For this, we are saying setGlyph(new vvv()), along with which we pass the colour that we want. Here, vvv is our class. Now we have to say that our class extends Glyph. Glyph has three virtual functions paint(), getWidth() and getHeight(), which also have to be included within this class. In our constructor we have passed the parameter r which looks like Color. However, r will die at the end of this constructor, that is why we save it in a variable, c, to make it available throughout the class. Now paint gets called . This function first saves the current colour of the screen. We set the drawing colour to the colour we want, that is, red. We then create a rectangle for which we obtain the height and width from the other two virtual functions in Gylph, namely, getWidth() and getHeight(). Finally we set the drawing colour to the original colour that we had saved in o for the screen to be repainted, otherwise, in future, everything on screen will be painted with only the colour red .

zzz.java

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;
import com.sun.java.swing.text.*;

public class zzz extends JPanel 
{
static JFrame frame;
public zzz()    
{
JMenuBar m = new JMenuBar();
JMenu f = new JMenu ("File");
f.setGlyph(new ImageGlyph("folder.gif"));
f.setHorizontalTextPosition(JButton.RIGHT);

JMenuItem o=new JMenuItem("Open",new ImageGlyph("open.gif"));
o.setHorizontalTextPosition(JButton.RIGHT);
f.add(o);

m.add(f);

JMenu gg = new JMenu ("Color");
gg.setGlyph(new vvv(Color.red));
gg.setHorizontalTextPosition(JButton.RIGHT);

JMenuItem red=new JMenuItem("Red");
gg.add(red);
red.setGlyph(new vvv(Color.red));
red.setHorizontalTextPosition(JButton.RIGHT);

JMenuItem blue=new JMenuItem("Blue");
blue.setGlyph(new vvv(Color.blue));
gg.add(blue);
blue.setHorizontalTextPosition(JButton.RIGHT);

m.add(gg);
m.validate();
add(m);
}
public static void main(String s[ ])
{
frame = new JFrame("hi");
frame.add("Center", new zzz());
frame.pack();
frame.setVisible(true);
}
}

class vvv implements Glyph
{
Color c;
vvv( Color r)
{
this.c = r;
}
public void paint(Graphics g,int x,int y)
{
Color oc=g.getColor();
g.setColor(c);
g.fill3DRect(x,y,getWidth(),getHeight(),true);
g.setColor(oc);
}
public int getWidth(){return 15;}
public int getHeight(){return 15;}
}

When we are doing these programs, we have to remember the heirarchy of the terms involved. At the top of this heirachy is the menubar. The menubar has to be filled with menus. There may be a number of menus within a menubar and they will all appear in the same line on the screen. Each menu may have a number of menu items which appear just below the menu, when we click on the menu. Here, a single menuitem called 'Open' is added to our first menu, 'File'. For our second menu 'Color', we have added two menuitems, namely red and blue. The entire procedure is the same as in the previous program.

zzz.java

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;
import com.sun.java.swing.text.*;

public class zzz extends JPanel {
static JFrame frame;
public zzz()    {
JMenuBar m = new JMenuBar();

JMenu f = new JMenu ("File");
f.setGlyph(new ImageGlyph("folder.gif"));
f.setHorizontalTextPosition(JButton.RIGHT);

JMenuItem o=new JMenuItem("Open",new ImageGlyph("open.gif"));
o.setHorizontalTextPosition(JButton.RIGHT);
f.add(o);

JMenuItem e=new JMenuItem("Exit");
e.setHorizontalTextPosition(JButton.RIGHT);
f.add(e);
e.addActionListener(new aa());
m.add(f);
add(m);
}
public static void main(String s[ ])
 {
frame = new JFrame("hi");
frame.add("Center", new zzz());
frame.pack();
frame.setVisible(true);
}
}
class aa implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}

}

As usual, we have a menubar to which we add menus. The menus, themselves, may consist of a number of menuitems. Until now, we have been only displaying these menuitems. Wouldn't it be useful if we were able to click on a menuitem and perform some task. For this, we shall obviously need an ActionListener. With our menuitem 'Exit', we say addActionListener (new aa()). aa has to implement ActionListener. This interface has one function, actionPerformed(), which contains the code System.exit(0). This results in us getting out of this application. We could, instead, have performed some other useful task using this function, with this type of an application.

zzz.java

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;

public class zzz extends JPanel {
static JFrame frame;
public zzz()    {
add("Center ", new ListPanel());
}
 public static void main(String s[ ])
{
frame = new JFrame("hi");
frame.add("Center", new zzz());
frame.pack();
frame.setVisible(true);
}
}
class ListPanel extends JPanel
{
JListBox l;
JListDataModel m=new JListDataModel();
public ListPanel(){
for (int i=0; i<4;i++)
	m.addElement(new Integer(i));
 l = new JListBox(m);
add(l);
}
}
}

We now move on to Listboxes. These are simply boxes which have a number of cells which can be selected one at a time. When the cell is selected, it automatically gets highlighted. As usual, main gets called first, where we say new zzz(), to call the constructor of zzz. From the constructor of class zzz, we are calling the constructor of ListPanel. In class ListPanel we have created a variable m that looks like JListDataModel. We also have a parameter l that looks like JListBox. Here we have added four elements to m. Integer is a new class given to us by Sun, of which 'int' is a merely a subclass. When we create a listbox, we need to give it a JListDataModel, which is why we have passed m out here. Finally we say add (l) which adds our listbox to our panel. When we run the program, we see the numbers 0, 1, 2 , 3 in the listbox, one below the other. We may click on any one of these numbers, and they will get selected. In the for loop, we can now replace the 0 and 4 by 100 and 104 respectively and see the result.

zzz.java

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;

public class zzz extends JPanel
{
        public zzz()
        {
        add("Center",new ListPanel());
        }
        public static void main(String s[])
        {
        JFrame frame = new JFrame("hi");
        frame.add("Center", new zzz());
        frame.pack();
        frame.setVisible(true);
        }
 }
class ListPanel extends JPanel 
{
JListBox l;
JListDataModel m = new JListDataModel();
public ListPanel()
{
    for(int i = 0; i < 4; i++)
    {
            m.addElement(new Integer(i));
    }
        l = new JListBox(m);
        l.setCellRenderer(new te());
        add(l);
}
 }
 class te extends JLabel implements Renderer
 {
 ImageGlyph im[ ];
 String dsc[ ];
 int price[ ];
         public te()
         {
           im=new ImageGlyph[4];
           dsc=new String[4];
           price=new int[4];
           im[0]=new ImageGlyph("burger.gif");
           im[1]=new ImageGlyph("icecream.gif");
           im[2]=new ImageGlyph("fries.gif");
           im[3]=new ImageGlyph("grapes.gif");
           dsc[0]="burger";
           dsc[1]="icecream";
           dsc[2]="fries";
           dsc[1]="grapes";
           price[0]=1;
           price[1]=2;
           price[2]=3;
           price[3]=4;
        }
        public void setValue(Object v,boolean iss)
        {
        int i=((Integer)v).intValue();
        System.out.println("setValue"+i+" "+iss);
        if(!iss)
        setText(" "+dsc[i]);
        else 
        setText(""+dsc[i]+" "+price[i]);
        setGlyph(im[ i ]);
        }
        public Component getComponent()
        {
        System.out.println("get");
        return this;
        }

}

Listboxes are the kind of examples that we were talking a lot about. In the previos program we only displayed numbers. However we have always said that the nice thing about the Java Foundation Classes is that where ever we display numbers ,we may also display pictures. Now, listbox has a function called setCellRenderer. Here, the statement, new te (), will obviously call the constructor of class te. Within the class te, all that we have done is a series of initialisations. Now te has to look like Renderer. Therefore we have said te implements Renderer. Renderer have two virtual functions. One is setValue () and the other is getComponent (). The first function to get called is getComponent(). The return value of getComponent() is of type Component. When we say 'return this', it means that it can return either a te or a JLabel or a Renderer. But here since we can return only a component, we return a JLabel. Now, setValue() gets called. Here, the Object is what we have returned in the function getComponent(), namely our JLabel. It is, however, not useful to us, as far as processing data is concerned, if the object is a component. This is why we are casting it to an Integer. The class Integer has a function, intValue(), which will return the object's value. . Therefore i will now have the current value of the item or cell within the listbox. The boolean parameter is used to find out whether we have selected that particular item or not. In case it has been selected, we also print the price along with the picture, otherwise we only display the picture. The actual displaying of the picture within each cell is done by setGlyph(). We have to call our renderer each time a cell has to be painted, which is why we may notice setValue() and getComponent() being called a number of times from whatever System.out.println() displays our at our DOS prompt.

Assume we are using an Operating System like Windows95 and we are in the main Window. Take a case where a part of this window is overwritten by another window. At this point in time, Windows95 will claim that it is not its responsibility to draw whatever is in that window. Suppose we finish our work in the second window and if we come back to our original window. Then the Windows operating system will tell our window that a part of it has been dirtied. Therefore our window needs to be repainted. Windows95 does this by sending our window a paint message. Suppose we had some text on our screen. A part of this text was in the section that had been overwritten. Now we have to rewrite the text using the windows SDK command TextOut. This command has to be given within the function paint. Windows95 is a very smart operating system and knows how to optimise time. This is, I suppose, for lowly people who are forced to run Windows95 on 486s, but it does save on time when a number of complex items have to be redrawn. Getting back to our textout command in paint, the complete text is not rewriiten. Only the part of the text that had been overwritten is now redrawn. Notice that we have said 'redrawn' and not 'rewritten'. As far as Windows is concerned, it treats everything that has to go on to screen as a series of pixels. Therefore, text as well as images are treated the same way.

There are a few new things that the java foundation classes have provided us that make our applets or applications better looking. Not only that, the way our applets look, can be changed, depending on what the user wants it to look like. Take for instance the case of a button. People who use windows95 will want a button that looks like a windows95 button, while a person who is used to a Macintosh will want the same button to be in the Mac style. This poses a dilemma. Should we keep the button looking the same irrespective of the Operating System or should the button have the look and feel of the particular operating System it is running under. The JDK1.0 used the second option and what it did was to have the button drawn by the operating system itself. There was one problem with this approach. Suppose you had earlier worked on an application on the Mac, and now you switched on to say an Intel machine with windows on it. You will realise that the same application looks very different under your new operating system. So what the JFCs decided to do was a very simple thing. They gave the user the option of changing the look and feel. This was a very smart thing to do. After all, when we go to work, our dress is very formal. However, if we have to attend a party with friends, we won't go wearing the same clothes. We would rather change in to jeans and T-shirts. Something similar can be done with the JFCs. If our application is running under Windows95, but if we do not like it's look and feel, we may change it to another look and feel that is either supplied by Sun or has been created by us. This option is available to us at runtime, and enables us to decide how our application will be displayed. Earlier, if we were using Windows95, we didn't have an option as to how our application would be displayed. Windows95 itself decided how it would be displayed. Now with the JFCs we have a very flexible look and feel. We call this the Plugable Look and Feel.

zzz.java

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;

public class zzz extends JPanel
{
      static JFrame frame;
        public zzz()
        {
             JRadioButton tiger = new JRadioButton("tiger");
             JRadioButton lion = new JRadioButton("lion");
             add(tiger);  
             add(lion);
           }
        public static void main(String s[ ])
        {
         frame = new JFrame("hi");
        frame.add("Center", new zzz());
        frame.pack();
        frame.setVisible(true);
        }
 }

When we execute this program, we see two radiobuttons on our screen, with the text 'tiger' or 'lion' written just beneath them.

zzz.java

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;

public class zzz extends JPanel
{
static JFrame frame;
public zzz()
{
  JRadioButton tiger = new JRadioButton("tiger");
  JRadioButton lion = new JRadioButton("lion");
  add(tiger);  
  add(lion);
  try
  {
  UIManager.setUIFactory("com.sun.java.swing.basic.BasicFactory",frame);                 }
  catch(ClassNotFoundException err)
  {
   System.out.println("error message");
  }  
  frame.pack();	
}
public static void main(String s[ ])
{
 frame = new JFrame("hi");
 frame.add("Center", new zzz());
 frame.pack();
 frame.setVisible(true);
}
}

Earlier, we had spoken about the ability of the Java Foundation Classes to change the look and feel of a component, according to what the user desires. In this program, we shall actually see how this is implemented. To achieve this change in the user interface, we make use of a static object called UIManager.

This has a static function called setUIFactory(). This will set the look and feel within our frame, to whatever we have specified. Here, we have specified that we want a 'basic' look and feel. Basic refers to a Windows95 look and feel. When we run the program, we see radiobuttons, as we would under Windows95.

Within setUIFactory(), if we instead had to write com.sun.java.swing.rose.RoseFactory, and run this program we wouldn't see radio buttons as they appeared in Windows95. The radio buttons would now appear different and, I'm happy to say, better looking. Notice that we have changed only the last two terms in the first parameter of the setUIFactory function. In other words, we may only change what appears after com.sun.java.swing.rose. What we mean by this statement is that the procedure of creating the button always remains the same. What changes, is how it appears on the screen, at runtime.

Now, we come to the concept of try and catch. If we see the term 'try', it literally means that we have to attempt to execute whatever code follows this term, within the curly brackets. Along with a 'try', we have to have the term 'catch'. In case the code after the 'try' cannot be executed sucessfully, an error or an exception will be generated. This exception will be caught by the 'catch' statement. In this program, the setUIFactory function will generate a ClassNotFoundException if we, for example, change the spelling of basic to baaaasic. At our dos prompt, we then see the text 'error message'.

zzz.java

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;

public class zzz extends JPanel implements ActionListener
{
static JFrame frame;
public zzz()
{
JRadioButton tiger = new JRadioButton("tiger");
JRadioButton lion = new JRadioButton("lion");
add(tiger);  
add(lion);
try
{
UIManager.setUIFactory("com.sun.java.swing.basic.BasicFactory",frame);	
}
catch(ClassNotFoundException err)
{
System.out.println("error message");
}
frame.pack();
tiger.addActionListener(this);
lion.addActionListener(this);  
}
public void actionPerformed(ActionEvent e)
{
System.out.println("hi");
}
public static void main(String s[ ])
{
frame = new JFrame("hi");
frame.add("Center", new zzz());
frame.pack();
frame.setVisible(true);
}
}	

Now, when we click on the any of the radio buttons, at the DOS prompt, we see 'hi', for as many times as we have clicked on the buttons.

zzz.java

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;

public class zzz extends JPanel implements ActionListener
{
static JFrame frame;
public zzz()
{
JRadioButton tiger = new JRadioButton("basic");
JRadioButton lion = new JRadioButton("rose");
add(tiger);  
add(lion);
tiger.addActionListener(this);
lion.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
String aaa=null;
if(e.getActionCommand() == "rose")
aaa="com.sun.java.swing.rose.RoseFactory";
else
aaa="com.sun.java.swing.basic.BasicFactory";
try
{
UIManager.setUIFactory(aaa,frame);
frame.pack();
}
catch(ClassNotFoundException err)
{
System.out.println("error message");
}
}
public static void main(String s[ ])
{
frame = new JFrame("hi");
frame.add("Center", new zzz());
frame.pack();
frame.setVisible(true);
}
}

We come to a program which will demonstrate how we can change the look and feel of a button in run time. We have changed the text of the radiobutton tiger to 'basic', and that of lion to 'rose', just for our convenience. Here, getActionCommand is a function in ActionEvent, which returns the name of the component calling it . Depending on which button we have clicked on, the look and feel will change to either rose or basic.

Now we come to the concept of 100% Pure Java. Right now we are using the JDK1.1.3 which is merely an updated version of the JDK1.1.2. But underneath it all, is the JDK1.1. All that JDK1.1.3 did was to call code. This code if it had to run under windows95 would have to be in a DLL. So that is where we call it from. This may further call code in other windows95 DLLs which will finally call code in VxDs. Now when we say 100% Pure Java, we mean that our JFCs are basically .class files that are executed. In none of these .class files, do we call native code. In other words, we donot call any 'C' code. We can however call code from the JDK1.1 which in turn may call native code. But the JFCs remain 100% Pure Java.

We have put up some more programs out here , for which the explanations will be given as soon as time permits. For now, just try running them. They should not be too difficult to understand.

zzz.java

import java.awt.*;
import com.sun.java.swing.*;
public class zzz extends JPanel 
{
static JFrame frame;
public zzz()
{
setLayout(new BorderLayout());
add("Center",new ttt());
}
public static void main(String s[ ])
{
frame = new JFrame("zzz");
frame.add("Center", new zzz());
frame.pack();
frame.setVisible(true);
}
}
class ttt extends JPanel
{
public ttt()
{
setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
ccc c = new ccc();
c.setToolTipText("Cow");
add(Box.createRigidArea(new Dimension(1,40)));
add(c);
}
class ccc extends JLabel
{
public ccc()
{
super(new ImageGlyph("cow.gif"));
}
public boolean contains(int x, int y)
{
if ((x>30) && (x < 60) && (y > 60) && (y<85))
{
setToolTipText("Moooo");
}
if ((x>150) && (x < 230) && (y > 90) && (y<145))
{
setToolTipText("Milk");
}
if ((x>280) && (x < 300) && (y > 20) && (y<175))
{
setToolTipText("Tail");
}
return true;
}
}
}



zzz.java
import java.awt.*;
import java.lang.*;
import com.sun.java.swing.*;
public class zzz extends JPanel 
{
static JFrame f;
JTabbedPane t;
public zzz()
{
setLayout(new BorderLayout());
t = new JTabbedPane();
ImageGlyph s = new ImageGlyph("swingLabelSmall.gif");
JPanel j = lll();
t.addTab(" ",s,j);
t.addTab("Vijay",null,new JPanel());
add(t);
}
JPanel lll()
{
JPanel p = new JPanel();
ImageGlyph l = new ImageGlyph("AboutSwing.gif");
p.add(new JLabel(l));
return p;
}
public static void main(String s[])
{
f = new JFrame("hi");
zzz z = new zzz();
f.add("Center",z);
f.pack();
f.setVisible(true);
}
}

zzz.java

import java.awt.*;
import java.lang.*;
import java.awt.event.*;
import com.sun.java.swing.*;
public class zzz extends JPanel 
{
static JFrame f;
public zzz()
{
setLayout(new BorderLayout());
add("Center", new iii());
}
public static void main(String s[])
{
f = new JFrame("hi");
zzz z = new zzz();
f.add("Center",z);
f.pack();
f.setVisible(true);
}
}
class iii extends JPanel implements ActionListener
{
JTextField lf;
JLayeredPane lc;
JInternalFrame m;
JButton mk;
int cnt = 0;
public iii()
{
setLayout(new BorderLayout());
lc = new JLayeredPane();
m = ccc();
lc.add(m);
add("Center",lc);
}
public JInternalFrame ccc()
{
JInternalFrame w;
JTitledPane tp;
w = new JInternalFrame("Frame Creator");
w.setLayer(JLayeredPane.PALETTE_LAYER);
w.setLayout(new GridLayout(0,1));
tp = new JTitledPane();
tp.setTitle("Layer");
tp.setLayout(new BorderLayout());
lf= new JTextField();
lf.setMinimumSize(new Dimension(50,25));
lf.setEditable(true);
lf.setText("5");
tp.add(lf, "Center");
w.add(tp);
tp = new JTitledPane();
tp.setBorder(null);
tp.setLayout(new GridLayout(1,2));
mk = new JButton("Make");
mk.addActionListener(this);
tp.add(mk);
w.add(tp);
w.setBounds(200,10,200,250);
w.setResizable(true);
return w;
}
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == mk)
{
JInternalFrame w;
int l;
w = new JInternalFrame();
l = Integer.parseInt(lf.getText());
w.setLayer(l);
cnt++;
w.setBounds(10*cnt,10*cnt,150,100);
w.setContentView(new vvv(l));
lc.add(w);
w.setMain(true);
}
}
}
class vvv extends JComponent
{
int ml;
public vvv( int y)
{
ml = y;
}
public void paint(Graphics g)
{
g.drawString("Layer " + ml,(getWidth()/3),(getHeight()/3));
}
}


zzz.java
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import com.sun.java.swing.*;
import com.sun.java.swing.text.*;
import com.sun.java.swing.basic.BasicComboBoxUI;
public class zzz  extends JPanel
{
static JFrame frame;
public zzz(){
 TreeNode sn = new TreeNode("ABCD");
 TreeNode api = new TreeNode("PQR");
 api.add(new TreeNode("XYZ"));
 sn.add(api);
 ttt tc = new ttt(new JTreeModel(sn));
 add(tc);
}
public static void main(String s[])
{
 frame = new JFrame ("zzz");
 frame.add("Center",new zzz());
 frame.pack();
 frame.setVisible(true);
}
}
class ttt extends JComboBox
{
 public ttt(TreeModel aTreeModel)
 {
 setModel(new ttl(aTreeModel));
 super.setUI(new tcu());
 }
 public void configureCurrentValueRenderer(Renderer a, Object v)
 {
 rrr r = (rrr) a;
 r.setComputeOffset(false);
 r.setValue(v,true);
 r.setComputeOffset(true);
 }
 class ttl extends JListDataModelAdapter implements ComboBoxDataModel, TreeModelListener
 {
 TreeModel s;
 boolean i = true;
 Object cv;
 Vector ch = new Vector();
 public ttl(TreeModel l)
 {
 s = l;
 l.addTreeModelListener(this);
 setRenderer(new rrr());
 }
 public void setCurrentValue(Object an)
 {
 cv = an;
 notifyListDataListeners(new ListDataEvent(this,ListDataEvent.CONTENTS_CHANGED,-1,-1));
 }
 public Object getCurrentValue()
 {
 return cv;
 }
 public int getSize()
 {
 if(i)
 {
 ch = new Vector();
 cacheTree(s.getRoot(),0);
 if(ch.size() > 0)
 cv = ch.elementAt(0);
 i=false;
 notifyListDataListeners(new ListDataEvent(this,ListDataEvent.CONTENTS_CHANGED,0,0));
 }
 return ch.size();
 }
 public Object getElementAt(int n)
 {
 return ch.elementAt(n);
 }
 public void treeNodesChanged(TreeModelEvent e){}
 public void treeNodesInserted(TreeModelEvent e){}
 public void treeNodesRemoved(TreeModelEvent e){}
 public void treeStructureChanged(TreeModelEvent e){}
 void cacheTree(Object an, int level)
 {
         if (s.isLeaf(an))
         addListEntry(an,level,false);
         else
         {
         int c = s.getChildCount(an);
         int i;
         Object child=null;
         addListEntry(an,level,true);
         level++;
         for(i=0;i<c;i++)
         child=s.getChild(an,i);
         cacheTree(child,level);
        }
        level--;
}

void addListEntry(Object an, int level, boolean isNode)
{
ch.addElement(new lll(an,level,isNode));
}
}
}
class lll
{
Object ob;
int level;
boolean is;
public lll(Object an,int aLevel, boolean in)
{
ob = an;
level = aLevel;
is=in;
}
public Object object()
{
return ob;
}
public int level()
{
return level;
}
public boolean is()
{
return is;
}
}
class EntryParent extends JComponent
{
JLabel label;
public void paint(Graphics g)
{
Rectangle b = label.getBounds();
Graphics cg = g.create(b.x,b.y,b.width,b.height);
label.paint(cg);
cg.dispose();
}
void setLabel(JLabel aLabel)
{
label = aLabel;
add(label);
}
}
class rrr implements Renderer
{
JLabel label;
EntryParent parent;
boolean shouldComputeOffset = true;
ImageGlyph leafGlyph = new ImageGlyph("document.gif");
ImageGlyph nodeGlyph = new ImageGlyph("folder.gif");
public rrr()
{
label = new JLabel();
parent = new EntryParent();
parent.setLabel(label);
}
public void setComputeOffset(boolean aFlag)
{
shouldComputeOffset = aFlag;
}
public void setValue(Object value, boolean isSelected)
{
lll le = (lll)value;
Dimension d;
int o;
if (le != null)
{
label.setText(le.object().toString());
if (le.is())
label.setGlyph(nodeGlyph);
else
label.setGlyph(leafGlyph);
if(shouldComputeOffset)
o = (16 * le.level());
else
o = 0;
label.setLocation(o,0);
d=label.getPreferredSize();
label.setSize(d.width,d.height);
d.width +=o;
parent.setSize(d.width,d.height);
}
else
{
label.setText("");
d=label.getPreferredSize();
parent.setSize(d);
label.setLocation(0,0);
}
}
public Component getComponent()
{
return parent;
}
}
class tcu extends BasicComboBoxUI
{
protected JListBox createListBox(ComboBoxDataModel m)
{
JListBox res = new JListBox(m);
res.setCellRenderer(new rrr());
return res;
}
}


The above is a joint effort of

Mr. Vijay Mukhi
Mr. Vinod Rasquinha
Ms. Sonal Kotecha
Mr. Vivek Agarwal


Back to the main page


Vijay Mukhi's Computer Institute
VMCI, B-13, Everest Building, Tardeo, Mumbai 400 034, India
Tel : 91-22-496 4335 /6/7/8/9     Fax : 91-22-307 28 59
e-mail : [email protected]
http://www.vijaymukhi.com/