All mothers of the world 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 five 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 in 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. If you do not understand this program, then refer to the chapter titled
'Shlurrp Java'. We compile this program using javac and then using Appletviewer
we open a.html to run this file. All that this program does is place a Button on our screen,which says 'Hi', This is the type of output we get when we use the original JDK1.x. 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 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'. >javac zzz.java 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. 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?'.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 zzz.java You mean we went through that much trouble just to get something that looked as bad as the best that JDK1.x 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? In case you are wondering whether to go further in this chapter, 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 Before you run this program within your java subdirectory, move to demo\jfc\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 ImageIcon. ImageIcon 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 ImageIcon using our .gif file and adding this ImageIcon to our button. The image contained in buttonImage3.gif file is pasted on to our button. Earlier when we used button, all we could do was 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. But, right now, we can stop meditating because
the JFCs are here, and we have work to do. This is probably an 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. In this program, we have created two ImageIcons. The only thing new in
this program is the line b.setPressedIcon(j). Here, we obviously mean
that 'setPressedIcon' 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 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. A point to be remembered here is that when we say b.setRolloverIcon( ) ,we obviously mean that the function setRolloverIcon 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 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.setDisabledIcon(j) simply says that when b has been disabled, replace
the first ImageIcon 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. 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 zzz.java 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. The function addItemListener however, demands that it requires an object that is an ItemListener. This is now shown in the next program. zzz.java In this program we have to make sure that our current object is an ItemListener. ItemListener is an interface so we use 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 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.x. 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 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 is
called. This is how we handle events in the Java Foundation Classes. 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 ImageIcon. Every JLabel has a function setIcon( ). We place our Image Icon within this function. When we execute this program, our label now contains an image as well as the text, side by side. zzz.java In this program, we have created an ImageIcon as we had done earlier. We have added this ImageIcon 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
zzz.java All that we have done out here is to write getViewport( ).add( l ) instead
of zzz.java 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,
let's 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 When we click on the button for the first time, the initial value is 10, 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 use the progressbar's pointer to increment by a fixed amount, but the concept remains the same. zzz.java If you look at any music system, you'll notice that you can adjust the volume or the bass 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, Windows 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 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 To deal with problems that we may encounter with any graphics application
in java, we have a static object named DebugGraphics. This static object
has a function named 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 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. Normally, 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 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 In an application, the first function to be called is always main(). The reason 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 zzz.java 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 ! zzz.java As we said earlier, the first function to be called in an application
is main(). zzz.java While 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 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. Listboxes are the kind of examples that we were talking a lot about.
In the Assume we are using an Operating System like Windows 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, Windows 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. Windows
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. Windows is a very
smart operating system and knows how to optimise time. This is, I suppose,
for people who are forced to run Windows on 486s, but it does save on
time when a number of complex items have Take for instance the case of a button. People who use Windows will want a button that looks like a Windows 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 Windows, 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 Windows, we didn't have an option as to how our application would be displayed. Windows 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. The Java Foundation Classes has the ability to change the look and feel of a component, according to what the user desires. To achieve this change in the user interface, we make use of a static object called UIManager. This has a static function called setLookAndFeel(). This will set the look and feel within our frame, to whatever we have specified. There are classes which refers to a Windows, Motif look and feel. Hence when we run the program, we see the objects displayed as per the platform we have selected. You can have these components show a neutral look too. Now we come to the concept of 100% Pure Java. Right now we are using
the JDK1.2.2 but underneath it all, is the JDK1.2. All that JDK1.2.2 did
was to call code. This code if it had to run under Windows would have
to be in a DLL. So that is where we call it from. This may further call
code in other Windows 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 do not call any 'C' code. We can however call code
from the JDK1.2 which in turn may call native code. But the JFCs remain
100% Pure Java.
|