46
CHAPTER 6. INTRODUCTION TO GUI PROGRAMMING
242
The best place to find URLs is on existing Web pages. Web browsers display the URL for the
page you are currently viewing, and many browsers will display the URL of a link if you point
to the link with the mouse.
If you are writing an HTML document and you want to make a link to another document
that is in the same directory, you canuse a relative URL. The relative URLconsists of just the
name of the file. For example, to create a link to a file named “s1.html” in the same directory
as the HTML document that you are writing, you could use
<a href="s1.html">Section 1</a>
There are also relative URLs for linking to files that are in other directories. Using relative
URLs is a good idea, since if you use them, you can move a whole collection of files without
changing any of the links between them (as long as you don’t change the relative locations of
the files).
When you type a URL into a Web browser, you can omit the “http://” at the beginning of
the URL. However, in an <a> tag in an HTML document, the “http://” can only be omitted if
the URL is a relative URL. For a normal URL, it is required.
∗ ∗ ∗
You can add images to a Web page with the <img> tag. (This is a tag that has no matching
closing tag.) The actual image must be stored in a separate file from the HTML document.
The <img> tag has a required modifier, named src, to specify the URL of the image file. For
most browsers, the image should be in one of the formats PNG (with a file name ending in
“.png”), JPEG (with a file name ending in “.jpeg” or “.jpg”), or GIF (with a file name ending
in “.gif”). Usually, the image is stored in the same place as the HTML document, and a relative
URL—that is, just the name of the file—is used to specify the image file.
The <img> tag also has several optional modifiers. It’s a good idea to always include the
height and width modifiers, which specify the size of the image in pixels. Some browsers
handle images better if they know in advance how big they are. The align modifier can be
used to affect the placement of the image: “align=right” will shove the image to the right edge
of the page, and the text on the page will flow around the image; “align=left” works similarly.
(Unfortunately, “align=center” doesn’t have the meaning you would expect. Browsers treat
images as if they are just big characters. Images can occur inside paragraphs, links, and
headings, for example. Alignment values of center, top, and bottom are used to specify how
the image should line up with other characters in a line of text: Should the baseline of the text
be at the center, the top, or the bottom of the image? Alignment values of right and left
were added to HTML later, but they are the most useful values. If you want an image centered
on the page, put it inside a <p align=center> tag.)
For example, here is HTML code that will place an image from a file named figure1.png on
the page.
<img src="figure1.png" align=right height=150 width=100>
The image is 100 pixels wide and 150 pixels high, and it will appear on the right edge of the
page.
6.2.4 Applets on Web Pages
The main point of this whole discussion of HTML is to learn how to use applets on the Web.
The <applet> tag can be used to add a Java applet to a Web page. This tag must have a
matching </applet>. A required modifier named code gives the name of the compiled class
46
CHAPTER 6. INTRODUCTION TO GUI PROGRAMMING
243
file that contains the applet class. The modifiers height and width are required to specify the
size of the applet, in pixels. If you want the applet to be centered on the page, you can put the
applet in a paragraph with center alignment. So, an applet tag to display an applet named
HelloWorldApplet centered on a Web page would look like this:
<p align=center>
<applet code="HelloWorldApplet.class" height=100 width=250>
</applet>
</p>
This assumes that the file HelloWorldApplet.class is located in the same directory with
the HTML document. If this is not the case, you can use another modifier, codebase, to give
the URL of the directory that contains the class file. The value of code itself is always just a
class, not a URL.
If the applet uses other classes in addition to the applet class itself, then those class files
must be in the same directory as the applet class (always assuming that your classes are all in
the “default package”; seeSubsection2.6.4; if not, they must be in subdirectories). If an applet
requires more than one or two class files, it’s a good idea to collect all the class files into a single
jar file. Jar files are “archive files” which hold a number of smaller files. If your class files are
in a jar archive, then you have to specify the name of the jar file in an archive modifier in the
<applet> tag, as in
<applet code="HelloWorldApplet.class" archive="HelloWorld.jar" height=50...
Iwill have more to say about creating and using jar files at the end of this chapter.
Applets can use applet parameters to customize their behavior. Applet parameters are
specified by using <param> tags, which can only occur between an <applet> tag and the closing
</applet>. The param tag has required modifiers named name and value, and it takes the
form
<param name="param-name" value="param-value">
The parameters are available to the applet when it runs. An applet uses the predefined method
getParameter() to check for parameters specifiedinparam tags. The getParameter() method
has the following interface:
String getParameter(String paramName)
The parameter paramName corresponds to the param-name in a param tag. If the specified
paramName actually occurs in one of the param tags, then getParameter(paramName) returns
the associated param-value. If the specified paramName does not occur in any param tag, then
getParameter(paramName) returns the value null. Parameter names are case-sensitive, so you
cannot use “size” in the param tag and ask for “Size” in getParameter. The getParameter()
method is often called in the applet’s init() method. It will not work correctly in the applet’s
constructor, since it depends on informationabout the applet’s environment that is not available
when the constructor is called.
Here is an example of an applet tag with several params:
<applet code="ShowMessage.class" width=200 height=50>
<param name="message" value="Goodbye World!">
<param name="font" value="Serif">
<param name="size" value="36">
</applet>
54
CHAPTER 6. INTRODUCTION TO GUI PROGRAMMING
244
The ShowMessage applet would presumably read these parameters in its init() method,
which could go something like this:
String message; // Instance variable: message to be displayed.
String fontName; // Instance variable: font to use for display.
int fontSize;
// Instance variable: size of the display font.
public void init() {
String value;
value = getParameter("message"); // Get message param, if any.
if (value == null)
message = "Hello World!"; // Default value, if no param is present.
else
message = value; // Value from PARAM tag.
value = getParameter("font");
if (value == null)
fontName = "SansSerif"; // Default value, if no param is present.
else
fontName = value;
value = getParameter("size");
try {
fontSize = Integer.parseInt(value); // Convert string to number.
}
catch (NumberFormatException e) {
fontSize = 20; // Default value, if no param is present, or if
}
//
the parameter value is not a legal integer.
.
.
.
Elsewhere in the applet, the instance variables message, fontName, and fontSize would be
used to determine the message displayed by the applet and the appearance of that message.
Note that the value returned by getParameter() is always a String. If the param represents
anumerical value, the string must be converted into a number, as is done here for the size
parameter.
6.3 Graphics and Painting
E
verything you see on a computer screen has to be drawn there, even the text. The
(online)
Java API includes a range of classes and methods that are devoted to drawing. In this section,
I’ll look at some of the most basic of these.
The physical structure of a GUI is built of components. The term component refers to a
visual element in a GUI, including buttons, menus, text-input boxes, scroll bars, check boxes,
and so on. In Java, GUI components are represented by objects belonging to subclasses of the
class java.awt.Component. Most components in the Swing GUI—although not top-level com-
ponents like JApplet and JFrame—belong to subclasses of the class javax.swing.JComponent,
which is itself a subclass of java.awt.Component. Every component is responsible for drawing
itself. If youwant to use a standardcomponent, you only have to add it to your applet or frame.
You don’t have to worry about painting it on the screen. That will happen automatically, since
it already knows how to draw itself.
Sometimes, however, you do want to draw on a component. You will have to do this
whenever you want to display something that is not included among the standard, pre-defined
48
CHAPTER 6. INTRODUCTION TO GUI PROGRAMMING
245
component classes. When you want to do this, you have to define your own component class
and provide a method in that class for drawing the component. I will always use a subclass
of JPanel when I need a drawing surface of this kind, as I did for the MessageDisplay class in
the exampleHelloWorldApplet.javain the previous section. A JPanel, like any JComponent,
draws its content in the method
public void paintComponent(Graphics g)
To create a drawing surface, you should define a subclass of JPanel and provide a custom
paintComponent() method. Create an object belonging to this class and use it in your applet
or frame. When the time comes for your component to be drawn on the screen, the system
will call its paintComponent() to do the drawing. That is, the code that you put into the
paintComponent() method will be executed whenever the panel needs to be drawn on the
screen; by writing this method, you determine the picture that will be displayed in the panel.
Note that the paintComponent() method has a parameter of type Graphics. The Graphics
object will be provided by the system when it calls your method. You need this object to
do the actual drawing. To do any drawing at all in Java, you need a graphics context. A
graphics context is an object belonging to the class java.awt.Graphics. Instance methods
are provided in this class for drawing shapes, text, and images. Any given Graphics object
can draw to only one location. In this chapter, that location will always be a GUI component
belonging to some subclass of JPanel. The Graphics class is an abstract class, which means
that it is impossible to create a graphics context directly, with a constructor. There are actually
two ways to get a graphics context for drawing on a component: First of all, of course, when
the paintComponent() method of a component is called by the system, the parameter to that
method is a graphics context for drawing on the component. Second, every component has
an instance method called getGraphics(). This method is a function that returns a graphics
context that can be used for drawing on the component outside its paintComponent() method.
The official line is that you should not do this, and I will almost always avoid it. But I have
found it convenient to use getGraphics() in a few examples.
The paintComponent() method in the JPanel class simply fills the panel with the panel’s
background color. When defining a subclass of JPanel for use as a drawing surface, you will
usually want to fill the panel with the background color before drawing other content onto
the panel (although it is not necessary to do this if the drawing commands in the method
cover the background of the component completely). This is traditionally done with a call to
super.paintComponent(g), so most paintComponent() methods that you write will have the
form:
public void paintComponent(g) {
super.paintComponent(g);
. . . // Draw the content of the component.
}
∗ ∗ ∗
Most components do, infact, do alldrawingoperations intheir paintComponent() methods.
What happens if, in the middle of some other method, you realize that the content of the
component needs to be changed? You should not call paintComponent() directly to make the
change; this method is meant to be called only by the system. Instead, you have to inform
the system that the component needs to be redrawn, and let the system do its job by calling
paintComponent(). You do this by calling the component’s repaint() method. The method
public void repaint();
40
CHAPTER 6. INTRODUCTION TO GUI PROGRAMMING
246
is defined in the Component class, and so can be used with any component. You should call
repaint() to inform the system that the component needs to be redrawn. It is important to
understand that the repaint() method returns immediately, without doing any painting itself.
The system will call the component’s paintComponent() method later, as soon as it gets a
chance to do so, after processing other pending events if there are any.
Note that the system can also call paintComponent() for other reasons. It is called when
the component first appears on the screen. It will also be called if the size of the component
changes, which can happen when the user resizes the window that contains the component. In
versions of Java earlier than Java 6, paintComponent() is also called if the component is covered
up and then uncovered, since the system did not automatically save a copy of the content. (And
even in Java 6, the content is not automatically saved if is drawnwitha graphics context created
by getGraphics(), as I will do in some examples.) In any case, paintComponent() should be
capable of redrawing the content of the component on demand. As you will see, however, some
of our early examples will not be able to do this correctly.
This means that, to work properly, the paintComponent() method must be smart enough
to correctly redraw the component at any time. To make this possible, a program should store
data in its instance variables about the state of the component. These variables should contain
all the information necessary to redraw the component completely. The paintComponent()
method should use the data in these variables to decide what to draw. When the program
wants to change the content of the component, it should not simply draw the new content. It
should change the values of the relevant variables and call repaint(). When the system calls
paintComponent(), that method will use the new values of the variables and will draw the
component with the desired modifications. This might seem a roundabout way of doing things.
Why not just draw the modifications directly? There are at least two reasons. First of all, it
really does turn out to be easier to get things right if all drawing is done in one method. Second,
even if you do make modifications directly, you still have to make the paintComponent()
method aware of them in some way so that it will be able to redraw the component correctly
on demand.
You will see how all this works in practice as we work through examples in the rest of this
chapter. For now, we will spend the rest of this section looking at how to get some actual
drawing done.
6.3.1 Coordinates
The screen of a computer is a grid of little squares called pixels. The color of each pixel can be
set individually, and drawing on the screen just means setting the colors of individual pixels.
x = 0
y = 0
y = height
x = width
Documents you may be interested
Documents you may be interested