![]() ![]() 16 September 2000 ![]() |
![]() |
Into Java, Part 9
If you ever have driven a completely new car you know that you have
to drive very slow and careful for a certain amount of kilometers not to damage the engine and transmission. But
how thrilling then when you have passed that limit and may step heavily on the gas. Now we have came to the first
limit of the Java programming scheme, we may step on the gas a few inches more. Today we will make us a HEX- and
RGB-driven color chooser that you may use upon creating the HTML code described in another article of this issue
of OS/2 e-Zine! |
||||||
Modeling the Objects
Any time we like to create ourselves a more complex application we
benefit from sketching a model of the objects we need using a pencil, that is the classes we need to implement,
how they will interact and the interface between them. In this column we will certainly not learn anything deeper
on modeling since that is a chapter of its own. Anyone interested may search for books on UML and patterns and
that way get readings for several years. |
|
java.awt.event
since we use the WindowAdapter class, and finally java.awt
since the Component and Color
classes resides there. Then we begin with our new class that inherits from JFrame. Since we will add three components
we declare them so that we are later able to refer to them. In fact we will never refer to the SliderPanel object,
but it does not hurthaving the variable at hand. The constructor is common to us, it is in fact close to a copy&paste
from the last time's installment, except for the last line of code in it, a call to
init()
.The last time we to some extent discussed the use of helper classes,
too, and this is no exception to the rule. Actually we are able to move out the complete code of the constructor
too, to another helper method, I think I will in future columns and that way leave some code to the reader to
type <grin>. The method name this time, init()
, is chosen so it will be more easy to convert this class into an applet later on
if you like to.
The init method is simply instantiating the different components
and adding them to the contentPane, as we are used to. If you mark some lines as comments you may compile and
run from here, without having to implement the other classes yet. This class will be named
ColorBox.java
, as a file of its own. Do not forget to
mark the last line of the method setColor
as
a comment too, since hexRgbPanel is still not ready to run.
As
you see we add the SliderPanel to the east of the main frame. The main frame, that is JFrame, uses a BorderLayout
as the default layout manager. It looks like the image to the right. Center is the one to be used to the main
component, this time the colorPane. We do not use North and hence that area will be empty, as the West side will.
But to the East we add the SliderPanel object, and to the South the HexRgbPanel object. So in fact, we only use
three of the five areas available with this manager. There are other layout managers as well, but we will
not use any of them today, only mention another one in a moment.
Anyway we see that we are not in the position to add the JSliders
to the contentPane one by one. Or the different text fields of the HexRgbPanel. It is much easier to add them
to JPanels and add only the panel that will act as a mere holder of the content. But since we inherit from JPanel
into a class of our own we may add some extra features to our class if we would like to, so we use the class inheriting
from JPanel both as a holder and a place for extra methods that we are implementing.
Then comes the method setColor(int
r, int g, int b)
. The most intuitive line is probably
the first line, it calls the colorPane
object's
method setBackground
with
a new Color as a parameter. setBackground
does
only take Color objects as arguments, so we need to instantiate one from the parameters
r, g
and b
. Color is found in the java.awt
package. Next line calls the method setValues
of the HexRgbPanel object, that we have not implemented
this far. Now we see that the SliderPanel object makes a call to the main frame's
setColor
that both sets the color of the colorPane
, but further pass the call
on to the HexRgbPanel object, that this method works as a telephone relay that pass on signals from a sender to
the receiver. Hence SliderPanel does not need to know about HexRgbPanel, the intermediate
setColor
method does the connection between them.
Finally the tiny driver that launches the rocket.
setValues(int r, int g, int b)
. This method has to know how to convert from the
three values given as parameters from the ColorBox's setColor
. Further we add labels to each text field.
|
Then comes the promised method. The first three lines is not much
to say about, except that the setText
method
of JTextField does only take String objects as parameters, we need to convert the integers to text strings and
I use a hack; make yourself a string and concatenate the integer to that string and Java will do the cast on the
fly. Yes, strings may be empty, they are still strings with a memory foot print of their own.
The next lines need a short explanation. To our relief Java offers
a convenient static method placed in the Integer class that converts integers to HEX values. Hence our only work
was to look that information up in our Java API, and, yes it can be tricky sometimes, especially when we do not
know were to look and if the answer is to be found at all. But you did it this time. Unfortunately this method
returns one digit HEX values if it is not above the ten based value of 15, that is 15 is converted to F, not 0F
as we would like to have it to be able to copy&paste it into our HTML pages. 16 is converted to 10 as should
be. Thus we look at the answer and if it is only one digit long we prefix it with an extra 0 (zero).
Further
we have to convert the color values one by one using a temporary string, and each one we have to test for this
one digit case before appending it to the resulting HEX string. Finally we can show the value, but we would like
to show it upper case. Done with this class! After saving this class as a file of its own, named
HexRgbPanel.java
, you now may remove most of the comment
marks, compile and run. Though still no values will change, we are in desperate need of the SliderPanel.
I might say that the default layout manager of the JPanel class
is FlowLayout. It works almost as its name, the items are added in a flow and nothing is promised about were the
object will end up, except that it will be between the previous and the next item. If a new row is needed to pour
objects into, anew row will be created by Java. But this is not always working as expected neither, as you may
see if you resize the main frame to a less wide size, the bottom panel is not "reflown", but some text
fields will be invisible. Still FlowLayout is useful this time, but be aware of the shortcomings.
SliderPanel.java
.)
|
owner
. The latter is new to us.Since we need to call the main frame's
setColor
we need to have a reference to that object.
I did not say much about it in the constructor of the ColorBox (actually the init
method), but look careful and you
will see that we pass on a reference this
to
the constructor of SliderPanel. Standing in the ColorBox object we are actually giving the reference to itself--this
--to the constructor of SliderPanel,
that catches and assigns it to the variable owner
.
This variable then work as the connector, or cable, to the setColor
method of the main frame.
Since FlowLayout is not always trustworthy we can force the sliders
to stand side by side, using a Box of horizontal type. The Box class resides in the Swing package and gives us
either horizontal or vertical boxes to fill. There is no limit how many items we may add to the box, but they
will always be placed side by side (horizontally) or on top of each other (vertical) the first item added lies
top most. When the box is filled we add the box to the panel, and the SliderPanel is ready to go.
The lines adding sliders to the box need an explanation. We may
split them into twoliners
but why should we when we can make them oneliners? Furthermore, what is taking place? Since there are quite a few lines looking the same upon creating the sliders we move them out into a helper method, that returns a fresh slider. So we assign a fresh slider tored = addSlider(Color.red, true);
box.add(red);
red, green
and blue
, taking a short tour through the helper method. But since we both will
give each slider a look of its own and as an extra option choose between two looks of the slider ticks, the marks,
we send both a Color object and a boolean as parameters. After the assignment we add the object to the box.Please look up the Java API and read more about the JSlider, I
have added some comments into the helper method, but there is much more to be said. We see how the boolean gives
us an opportunity to choose whether we would like to have major ticks or not. Note that we then have to tell Java
that we really would like to see the ticks too, only stating how narrow they will appear is not enough.
The color is added as the foreground color, visible only when the slider is used.
The the new listener comes, we add a listener named SliderChangeListener.
At the bottom of the SliderPanel class we find an anonymous inner class named so, SliderChangeListener. That class
implements, inherits from, the common ChangeListener that is normally used in conjunction with JSliders and a
few other Swing items. ChangeListener is an interface that says we have to implement the method public void stateChanged(ChangeEvent
e) {}
that in our case only calls the
setColor
method of the SliderPanel class. Using inner
classes this way gives us the benefit of having full access to every variable and method of the "surrounding"
class. Since we are not interested in exactly which slider being changed we do not need to parse the ChangeEvent
object this time. The SliderPanel's method setColor
parses all three sliders and calls the owner.setColor
with the three slider values as parameters.
this
as a parameter and the receiving class holds it, as a suggestion as the
variable owner
that is
easily understood. Then the next class can easily call owner.xxx
when needed. We found that the main frame had no problems passing on the
information to another class, using that class' object's variable. Sketching the objects always helps us finding
how the objects rely on each other and we may see the communication paths needed.Next time we will add to and remove from this frame, trying to
make it a PaintBox. CU around.
Previous Article |
Next Article |