Objects and Java Seminar
Applets, AWT Graphics, and Java 2D
Lecture Handout
Agenda
-
Introduce applets
-
Show you how to write an applet
-
Introduce AWT Graphics
-
Show you how to draw lines, circles, rectangles,...
-
Show you how to draw text
-
Describe XOR mode
-
Demonstrate animation
-
Describe the Java 2D API
Applets
-
A marketing device that hasn't lived up to its promise.
-
A dynamic extension of a Java application
-
An AWT widget:
The Applet Tag
<applet
CODE="Flasher.class"
CODEBASE="classes"
WIDTH=100 HEIGHT=75
>
</applet>
<applet
CODE="Flasher.class"
CODEBASE="classes"
WIDTH=50 HEIGHT=125
>
<param name="delayBetwPaints" value="2000">
<param name="color1" value="0x9966ff">
<param name="color2" value="0xff9933">
</applet>
Applet Methods
-
Three most fundamental methods in
Applet
to override are:
init()
- called first
start()
- called after init()
and each time page is revisited
stop()
- called when page is left and before destruction
-
Many other methods offer useful services:
- get a PARAM value from HTML tag
- get URL of enclosing doc (web page)
- download an audio clip or image
- show a string in the browser's status bar
- get references to all other applets in this doc
- ask the browser to go to a different page
How Flasher Works
-
Override the three fundamental methods:
init()
- grab parameters and initialize instance variables
start()
- create an animation thread that will repaint periodically
stop()
- stop the animation thread
-
Animation thread: wakes up periodically, switches the current color,
and calls
repaint()
.
-
repaint()
asks GUI to invoke paint()
.
-
Flasher
overrides paint()
to fill entire applet
panel with the current color.
AWT Graphics
-
Defined in
Component
:
repaint()
- request an update()
(app)
update()
- calls paint()
(GUI)
paint()
- draw a component
-
paint()
gets a Graphics
object:
public void paint(Graphics g) {
g.setColor(Color.green);
g.fillOval(5, 5, 20, 20);
}
The Flasher Applet
1 // In file appletsawt/examples/ex1/Flasher.java
2 import java.applet.*;
3 import java.awt.*;
4
5 public class Flasher extends Applet {
6
7 // delayBetweenPaints, color1, and
8 // color2 have default values assigned
9 // here, which can be overriden by parameters
10 // specified in the HTML applet tag.
11 private int delayBetweenPaints = 1000;
12 private Color color1 = Color.green;
13 private Color color2 = Color.blue;
14
15 private Runner runner;
16 boolean showColor1;
17
18 public void init() {
19
20 String delayStr = getParameter("delayBetwPaints");
21
22 if (delayStr != null) {
23 try {
24
25 delayBetweenPaints =
26 Integer.parseInt(delayStr);
27 }
28 catch (NumberFormatException e) {
29 }
30 }
31
32 String color1Str = getParameter("color1");
33
34 if (color1Str != null) {
35
36 try {
37
38 color1 = Color.decode(color1Str);
39 }
40 catch (NumberFormatException e) {
41 }
42 }
43
44 String color2Str = getParameter("color2");
45
46 if (color2Str != null) {
47
48 try {
49
50 color2 = Color.decode(color2Str);
51 }
52 catch (NumberFormatException e) {
53 }
54 }
55 }
56
57 private class Runner extends Thread {
58
59 private boolean stopRequested;
60
61 void requestStop() {
62 stopRequested = true;
63 }
64
65 public void run() {
66
67 for (;;) {
68
69 if (stopRequested) {
70 return;
71 }
72
73 showColor1 = !showColor1;
74
75 repaint();
76
77 try {
78 sleep(delayBetweenPaints);
79 }
80 catch (InterruptedException e) {
81 }
82 }
83 }
84 }
85
86 public synchronized void start() {
87
88 if (runner == null) {
89
90 runner = new Runner();
91 runner.start();
92 }
93 }
94
95 public synchronized void stop() {
96
97 if (runner != null) {
98
99 runner.requestStop();
100 runner = null;
101 }
102 }
103
104 public void paint(Graphics g) {
105
106 Dimension dim = getSize();
107
108 if (showColor1) {
109 g.setColor(color1);
110 }
111 else {
112 g.setColor(color2);
113 }
114
115 g.fillRect(0, 0, dim.width, dim.height);
116 }
117 }
Graphics
Methods
void paint(Graphics g) {
//...
}
g.drawRect(xStart, yStart, width, height);
g.fillRect(xStart, yStart, width, height);
g.drawRoundRect(xStart, yStart, width, height, arcWidth, arcHeight);
g.fillRoundRect(xStart, yStart, width, height, arcWidth, arcHeight);
g.draw3DRect(xStart, yStart, width, height, raised);
g.fill3DRect(xStart, yStart, width, height, raised);
1 // In file appletsawt/examples/ex2/DrawRectDemo.java
2 import java.applet.*;
3 import java.awt.*;
4
5 public class DrawRectDemo extends Applet {
6
7 private Color bgColor = Color.darkGray;
8 private Color fgColor = Color.yellow;
9
10 // border is the number of pixels beyond the edge
11 // of the panel that the shape begins
12 private static final int BORDER = 5;
13
14 public void init() {
15
16 String fgColorStr = getParameter("fgColor");
17
18 if (fgColorStr != null) {
19
20 try {
21
22 fgColor = Color.decode(fgColorStr);
23 }
24 catch (NumberFormatException e) {
25 }
26 }
27
28 String bgColorStr = getParameter("bgColor");
29
30 if (bgColorStr != null) {
31
32 try {
33
34 bgColor = Color.decode(bgColorStr);
35 }
36 catch (NumberFormatException e) {
37 }
38 }
39
40 setBackground(bgColor);
41 }
42
43 public void paint(Graphics g) {
44
45 Dimension dim = getSize();
46
47 int shapeWidth = dim.width - (2 * BORDER);
48 int shapeHeight = dim.height - (2 * BORDER);
49
50 int xShapeStart = BORDER;
51 int yShapeStart = BORDER;
52
53 g.setColor(fgColor);
54 g.drawRect(xShapeStart, yShapeStart, shapeWidth, shapeHeight);
55 }
56 }
More Graphics
Methods
g.drawOval(xStart, yStart, width, height);
g.fillOval(xStart, yStart, width, height);
g.drawArc(xStart, yStart, width, height, startAngle, arcAngle);
g.fillArc(xStart, yStart, width, height, startAngle, arcAngle);
g.drawPolygon(xPoints, yPoints, N_POINTS);
g.fillPolygon(xPoints, yPoints, N_POINTS);
g.drawLine(xStart, yStart, xEnd, yEnd);
g.drawImage(theImage, 0, 0, this);
1 // In file appletsawt/examples/ex2/DrawImageDemo.java
2 import java.applet.*;
3 import java.awt.*;
4 import java.net.URL;
5
6 public class DrawImageDemo extends Applet {
7
8 private Image theImage;
9
10 public void init() {
11
12 URL url = getDocumentBase();
13 theImage = getImage(url, "images/book.jpg");
14 }
15
16 public void paint(Graphics g) {
17
18 g.drawImage(theImage, 0, 0, this);
19 }
20 }
Fonts and Text
1 // In file appletsawt/examples/ex2/DrawTextDemo.java
2 import java.applet.*;
3 import java.awt.*;
4
5 public class DrawTextDemo extends Applet {
6
7 private Color bgColor = Color.darkGray;
8 private Color fgColor = Color.yellow;
9 private String labelString = "Howdy!";
10
11 // border is the number of pixels beyond the edge
12 // of the panel that the shape begins
13 private static final int BORDER = 5;
14
15 public void init() {
16
17 String fgColorStr = getParameter("fgColor");
18
19 if (fgColorStr != null) {
20
21 try {
22
23 fgColor = Color.decode(fgColorStr);
24 }
25 catch (NumberFormatException e) {
26 }
27 }
28
29 String bgColorStr = getParameter("bgColor");
30
31 if (bgColorStr != null) {
32
33 try {
34
35 bgColor = Color.decode(bgColorStr);
36 }
37 catch (NumberFormatException e) {
38 }
39 }
40
41 String labelString = getParameter("label");
42
43 if (labelString != null) {
44
45 this.labelString = labelString;
46 }
47
48 setBackground(bgColor);
49 }
50
51 public void paint(Graphics g) {
52
53 Dimension dim = getSize();
54
55 Font labelFont = new Font("Helvetica", Font.BOLD, 14);
56 FontMetrics fm = getFontMetrics(labelFont);
57
58 int labelStringWidth = fm.stringWidth(labelString);
59 int labelStringHeight = fm.getAscent();
60
61 int xStart = (dim.width - labelStringWidth) / 2;
62 int yStart =
63 ((dim.height - labelStringHeight) / 2) + labelStringHeight;
64 g.setColor(fgColor);
65 g.setFont(labelFont);
66 g.drawString(labelString, xStart, yStart);
67 }
68 }
XOR Mode
chocolate |
becomes |
scoop |
scoop |
becomes |
chocolate |
All Other Colors |
become |
Their Complement |
1 // In file appletsawt/examples/ex2/XORModeDemo.java
2 import java.applet.*;
3 import java.awt.*;
4 import java.awt.event.*;
5
6 public class XORModeDemo extends Applet {
7
8 private Color strawberry = new Color(0xcc, 0, 0x66);
9 private Color chocolate = new Color(0x66, 0x33, 0);
10 private Color vanilla = new Color(0xff, 0xff, 0x99);
11 private Color scoop = new Color(0x33, 0x99, 0xcc);
12
13 // border is the number of pixels beyond the edge
14 // of the panel that the shape begins
15 private static final int BORDER = 10;
16
17 public void init() {
18
19 setBackground(chocolate);
20
21 addMouseListener(
22
23 new MouseAdapter() {
24
25 public void mousePressed(MouseEvent e) {
26
27 Graphics g = getGraphics();
28
29 g.setColor(chocolate);
30 g.setXORMode(scoop);
31
32 Dimension dim = getSize();
33 int diameter = dim.height - (2 * BORDER);
34
35 int xStart = (dim.width / 2) - (diameter / 2);
36 int yStart = BORDER;
37
38 g.fillOval(xStart, yStart, diameter, diameter);
39
40 g.setPaintMode();
41 }
42 }
43 );
44 }
45
46 public void paint(Graphics g) {
47
48 Dimension dim = getSize();
49
50 int width = dim.width / 3;
51 int height = dim.height;
52
53 g.setColor(strawberry);
54 g.fillRect(0, 0, width, height);
55
56 g.setColor(vanilla);
57 g.fillRect(dim.width - width, 0, width, height);
58 }
59 }
Animation
1 // In file appletsawt/examples/ex3/FlickeryEclipse.java
2 import java.applet.*;
3 import java.awt.*;
4
5 public class FlickeryEclipse extends Applet {
6
7 private Color bgColor = Color.white;
8 private Color sunColor = Color.yellow;
9 private Color moonColor = Color.black;
10
11 private int delayBetweenPaints = 50;
12 private Runner runner;
13
14 private boolean moonGoesRightToLeft = true;
15 private int moonStep = 1;
16
17 // xMoon is initialized by paint(), the first time
18 // paint() gets called. paint() knows to do this
19 // because xMoonInitialized is false, and then sets
20 // xMoonInitialized to true.
21 private boolean xMoonInitialized = false;
22 private int xMoon;
23
24 // border is the number of pixels beyond the edge
25 // of the panel that the sun circle begins
26 private static final int BORDER = 3;
27
28 public void init() {
29
30 String delayStr = getParameter("delayBetwPaints");
31
32 if (delayStr != null) {
33 try {
34
35 delayBetweenPaints = Integer.parseInt(delayStr);
36 }
37 catch (NumberFormatException e) {
38 }
39 }
40
41 String bgColorStr = getParameter("bgColor");
42
43 if (bgColorStr != null) {
44
45 try {
46
47 bgColor = Color.decode(bgColorStr);
48 }
49 catch (NumberFormatException e) {
50 }
51 }
52
53 String sunColorStr = getParameter("sunColor");
54
55 if (sunColorStr != null) {
56
57 try {
58
59 sunColor = Color.decode(sunColorStr);
60 }
61 catch (NumberFormatException e) {
62 }
63 }
64
65 String moonColorStr = getParameter("moonColor");
66
67 if (moonColorStr != null) {
68
69 try {
70
71 moonColor = Color.decode(moonColorStr);
72 }
73 catch (NumberFormatException e) {
74 }
75 }
76
77 String moonDirStr = getParameter("moonDir");
78
79 if (moonColorStr != null) {
80
81 if (moonDirStr.equalsIgnoreCase("leftToRight")) {
82
83 moonGoesRightToLeft = false;
84 }
85 }
86
87 String moonStepStr = getParameter("moonStep");
88
89 if (moonStepStr != null) {
90 try {
91
92 moonStep = Integer.parseInt(moonStepStr);
93 }
94 catch (NumberFormatException e) {
95 }
96 }
97
98 setBackground(bgColor);
99 }
100
101 private class Runner extends Thread {
102
103 private boolean stopRequested;
104
105 void requestStop() {
106 stopRequested = true;
107 }
108
109 public void run() {
110
111 for (;;) {
112
113 if (stopRequested) {
114 return;
115 }
116
117 if (xMoonInitialized) {
118 if (moonGoesRightToLeft) {
119 xMoon -= moonStep;
120 }
121 else {
122 xMoon += moonStep;
123 }
124 }
125
126 repaint();
127
128 try {
129 sleep(delayBetweenPaints);
130 }
131 catch (InterruptedException e) {
132 }
133 }
134 }
135 }
136
137 public synchronized void start() {
138
139 if (runner == null) {
140
141 runner = new Runner();
142 runner.start();
143 }
144 }
145
146 public synchronized void stop() {
147
148 if (runner != null) {
149
150 runner.requestStop();
151 runner = null;
152 }
153 }
154
155 public void paint(Graphics g) {
156
157 Dimension dim = getSize();
158
159 int diameter = dim.height;
160 if (dim.width < dim.height) {
161
162 diameter = dim.width;
163 }
164
165 diameter -= 2 * BORDER;
166 int radius = diameter / 2;
167
168 // Find sun start location
169 int xCenter = dim.width / 2;
170 int yCenter = dim.height / 2;
171
172 int xSunStart = xCenter - radius;
173 int ySunStart = yCenter - radius;
174
175 g.setColor(sunColor);
176 g.fillOval(xSunStart, ySunStart, diameter, diameter);
177
178 if (!xMoonInitialized || (xMoon <= -diameter)
179 || (xMoon > dim.width)) {
180
181 if (moonGoesRightToLeft) {
182 xMoon = dim.width - 1;
183 }
184 else {
185 xMoon = 1 - diameter;
186 }
187 xMoonInitialized = true;
188 }
189
190 g.setColor(moonColor);
191 g.fillOval(xMoon, ySunStart, diameter, diameter);
192 }
193 }
Double Buffering
1 // In file appletsawt/example/ex4/Eclipse.java
2 import java.applet.*;
3 import java.awt.*;
4
5 public class Eclipse extends Applet {
6
7 private Color bgColor = Color.white;
8 private Color sunColor = Color.yellow;
9 private Color moonColor = Color.black;
10
11 private int delayBetweenPaints = 50;
12 private Runner runner;
13
14 private boolean moonGoesRightToLeft = true;
15 private int moonStep = 1;
16
17 // xMoon is initialized by paint(), the first time
18 // paint() gets called. paint() knows to do this
19 // because xMoonInitialized is false, and then sets
20 // xMoonInitialized to true.
21 private boolean xMoonInitialized = false;
22 private int xMoon;
23
24 // border is the number of pixels beyond the edge
25 // of the panel that the sun circle begins
26 private static final int BORDER = 3;
27
28 public void init() {
29
30 String delayStr = getParameter("delayBetwPaints");
31
32 if (delayStr != null) {
33 try {
34
35 delayBetweenPaints = Integer.parseInt(delayStr);
36 }
37 catch (NumberFormatException e) {
38 }
39 }
40
41 String bgColorStr = getParameter("bgColor");
42
43 if (bgColorStr != null) {
44
45 try {
46
47 bgColor = Color.decode(bgColorStr);
48 }
49 catch (NumberFormatException e) {
50 }
51 }
52
53 String sunColorStr = getParameter("sunColor");
54
55 if (sunColorStr != null) {
56
57 try {
58
59 sunColor = Color.decode(sunColorStr);
60 }
61 catch (NumberFormatException e) {
62 }
63 }
64
65 String moonColorStr = getParameter("moonColor");
66
67 if (moonColorStr != null) {
68
69 try {
70
71 moonColor = Color.decode(moonColorStr);
72 }
73 catch (NumberFormatException e) {
74 }
75 }
76
77 String moonDirStr = getParameter("moonDir");
78
79 if (moonColorStr != null) {
80
81 if (moonDirStr.equalsIgnoreCase("leftToRight")) {
82
83 moonGoesRightToLeft = false;
84 }
85 }
86
87 String moonStepStr = getParameter("moonStep");
88
89 if (moonStepStr != null) {
90 try {
91
92 moonStep = Integer.parseInt(moonStepStr);
93 }
94 catch (NumberFormatException e) {
95 }
96 }
97 }
98
99 private class Runner extends Thread {
100
101 private boolean stopRequested;
102
103 void requestStop() {
104 stopRequested = true;
105 }
106
107 public void run() {
108
109 for (;;) {
110
111 if (stopRequested) {
112 return;
113 }
114
115 if (xMoonInitialized) {
116 if (moonGoesRightToLeft) {
117 xMoon -= moonStep;
118 }
119 else {
120 xMoon += moonStep;
121 }
122 }
123
124 repaint();
125
126 try {
127 sleep(delayBetweenPaints);
128 }
129 catch (InterruptedException e) {
130 }
131 }
132 }
133 }
134
135 public synchronized void start() {
136
137 if (runner == null) {
138
139 runner = new Runner();
140 runner.start();
141 }
142 }
143
144 public synchronized void stop() {
145
146 if (runner != null) {
147
148 runner.requestStop();
149 runner = null;
150 }
151 }
152
153 public void update(Graphics g) {
154
155 paint(g);
156 }
157
158 public void paint(Graphics g) {
159
160 Dimension dim = getSize();
161
162 // Double buffer to reduce flicker
163 Image offscreenImage = createImage(dim.width, dim.height);
164 Graphics og = offscreenImage.getGraphics();
165
166 og.setColor(bgColor);
167 og.fillRect(0, 0, dim.width, dim.height);
168
169 int diameter = dim.height;
170 if (dim.width < dim.height) {
171
172 diameter = dim.width;
173 }
174
175 diameter -= 2 * BORDER;
176 int radius = diameter / 2;
177
178 // Find sun start location
179 int xCenter = dim.width / 2;
180 int yCenter = dim.height / 2;
181
182 int xSunStart = xCenter - radius;
183 int ySunStart = yCenter - radius;
184
185 og.setColor(sunColor);
186 og.fillOval(xSunStart, ySunStart, diameter, diameter);
187
188 if (!xMoonInitialized || (xMoon <= -diameter)
189 || (xMoon > dim.width)) {
190
191 if (moonGoesRightToLeft) {
192 xMoon = dim.width - 1;
193 }
194 else {
195 xMoon = 1 - diameter;
196 }
197 xMoonInitialized = true;
198 }
199
200 og.setColor(moonColor);
201 og.fillOval(xMoon, ySunStart, diameter, diameter);
202
203 g.drawImage(offscreenImage, 0, 0, this);
204 }
205 }
Java 2D API
Rendering Context
-
setStroke(Stroke)
- line point size, dashing
pattern, end-cap, join decorations
-
setPaint(Paint)
- solid colors, gradients, patterns
-
setComposite(Composite)
- overlap an existing object
-
setTransform(AffineTransform)
- applied to convert user to device space, can
rotate, scale, and shear
-
setClip(Shape)
- restricts rendering to area of any Shape
-
setFont(Font)
- convert text strings to glyphs
-
setRenderingHints(Map)
- preferences in trade-offs between speed
and quality. For example, antialiasing.
Rendering
-
draw(Shape s)
- renders outline of any geometry primitive, using
stroke and paint attributes (also drawOval()
, ...)
-
fill(Shape)
- renders any geometry primitive, by filling its interior
with the stroke and pattern specified by the paint attribute
-
drawString(String, ...)
- renders any text string. Font attribute used to
convert the string to glyphs, which are then filled with color or pattern
specified in paint attribute
-
drawImage(Image, ...)
- renders specified image
Graphics2D
Pipeline
-
Determine shape to be rendered:
- shape to
fill()
- simply transform
- shape to
draw()
-- use current stroke to turn outline into shape, transform outline shape
- text to
drawString()
- use current font to turn string into glyph shapes, transform glyph shapes
- image to
drawImage()
- transform image outline
-
Rasterize the shape: given ideal shapes, use rendering hints
to create coverage (alpha) values for actual pixels
-
Clip rasterized shape with current clipping shape
-
Determine colors: for filled shape, use current paint
attribute; for image, take colors from image
-
Combine colors with existing pixels: use current compositing
attribute
A 2D Eclipse
1 // In file appletsawt/example/ex5/Eclipse.java
2 import java.applet.*;
3 import java.awt.*;
4 import java.awt.geom.*;
5
6 public class Eclipse extends Applet {
7
8 private Color bgColor = Color.white;
9 private Color sunColor = Color.yellow;
10 private Color moonColor = Color.black;
11
12 private Image offscreen;
13
14 private int delayBetweenPaints = 50;
15 private Runner runner;
16
17 private boolean moonGoesRightToLeft = true;
18 private int moonStep = 1;
19
20 // xMoon is initialized by paint(), the first time
21 // paint() gets called. paint() knows to do this
22 // because xMoonInitialized is false, and then sets
23 // xMoonInitialized to true.
24 private boolean xMoonInitialized = false;
25 private int xMoon;
26
27 // border is the number of pixels beyond the edge
28 // of the panel that the sun circle begins
29 private static final int BORDER = 3;
30
31 public void init() {
32
33 String delayStr = getParameter("delayBetwPaints");
34
35 if (delayStr != null) {
36 try {
37
38 delayBetweenPaints = Integer.parseInt(delayStr);
39 }
40 catch (NumberFormatException e) {
41 }
42 }
43
44 String bgColorStr = getParameter("bgColor");
45
46 if (bgColorStr != null) {
47
48 try {
49
50 bgColor = Color.decode(bgColorStr);
51 }
52 catch (NumberFormatException e) {
53 }
54 }
55
56 String sunColorStr = getParameter("sunColor");
57
58 if (sunColorStr != null) {
59
60 try {
61
62 sunColor = Color.decode(sunColorStr);
63 }
64 catch (NumberFormatException e) {
65 }
66 }
67
68 String moonColorStr = getParameter("moonColor");
69
70 if (moonColorStr != null) {
71
72 try {
73
74 moonColor = Color.decode(moonColorStr);
75 }
76 catch (NumberFormatException e) {
77 }
78 }
79
80 String moonDirStr = getParameter("moonDir");
81
82 if (moonColorStr != null) {
83
84 if (moonDirStr.equalsIgnoreCase("leftToRight")) {
85
86 moonGoesRightToLeft = false;
87 }
88 }
89
90 String moonStepStr = getParameter("moonStep");
91
92 if (moonStepStr != null) {
93 try {
94
95 moonStep = Integer.parseInt(moonStepStr);
96 }
97 catch (NumberFormatException e) {
98 }
99 }
100 }
101
102 private class Runner extends Thread {
103
104 private boolean stopRequested;
105
106 void requestStop() {
107 stopRequested = true;
108 }
109
110 public void run() {
111
112 for (;;) {
113
114 if (stopRequested) {
115 return;
116 }
117
118 if (xMoonInitialized) {
119 if (moonGoesRightToLeft) {
120 xMoon -= moonStep;
121 }
122 else {
123 xMoon += moonStep;
124 }
125 }
126
127 repaint();
128
129 try {
130 sleep(delayBetweenPaints);
131 }
132 catch (InterruptedException e) {
133 }
134 }
135 }
136 }
137
138 public synchronized void start() {
139
140 if (runner == null) {
141
142 runner = new Runner();
143 runner.start();
144 }
145 }
146
147 public synchronized void stop() {
148
149 if (runner != null) {
150
151 runner.requestStop();
152 runner = null;
153 }
154 }
155
156 public void update(Graphics g) {
157
158 paint(g);
159 }
160
161 private void checkOffscreenImage() {
162
163 Dimension d = getSize();
164 if ((offscreen == null)
165 || (offscreen.getWidth(null) != d.width)
166 || (offscreen.getHeight(null) != d.height)) {
167
168 offscreen = createImage(d.width, d.height);
169 }
170 }
171
172 public void paint(Graphics g) {
173
174 Dimension dim = getSize();
175
176 // Double buffer to reduce flicker
177 checkOffscreenImage();
178 Graphics2D og2 = (Graphics2D) offscreen.getGraphics();
179
180 og2.setColor(bgColor);
181 og2.fillRect(0, 0, dim.width, dim.height);
182
183 int diameter = dim.height;
184 if (dim.width < dim.height) {
185
186 diameter = dim.width;
187 }
188
189 diameter -= 2 * BORDER;
190 int radius = diameter / 2;
191
192 // Find sun start location
193 int xCenter = dim.width / 2;
194 int yCenter = dim.height / 2;
195
196 int xSunStart = xCenter - radius;
197 int ySunStart = yCenter - radius;
198
199 // Define gradient points
200 Point2D p1 = new Point2D.Float(xCenter, yCenter);
201 Point2D p2 = new Point2D.Float(xSunStart + (radius / 3),
202 ySunStart + (radius / 3));
203
204 // Sun should have 4 horizontal gradient cycles
205 GradientPaint gp = new GradientPaint(p1, sunColor, p2, bgColor,
206 true);
207
208 // Create the shape for the sun
209 Ellipse2D sun = new Ellipse2D.Float(xSunStart, ySunStart,
210 diameter, diameter);
211
212 og2.setPaint(gp);
213 og2.fill(sun);
214
215 // Turn antialiasing on AFTER drawing the sun
216 og2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
217 RenderingHints.VALUE_ANTIALIAS_ON);
218
219 if (!xMoonInitialized || (xMoon <= -diameter)
220 || (xMoon > dim.width)) {
221
222 if (moonGoesRightToLeft) {
223 xMoon = dim.width - 1;
224 }
225 else {
226 xMoon = 1 - diameter;
227 }
228 xMoonInitialized = true;
229 }
230
231 // Create the shape for the moon
232 Ellipse2D moon = new Ellipse2D.Float(xMoon, ySunStart,
233 diameter, diameter);
234
235 Composite compo = AlphaComposite.getInstance(
236 AlphaComposite.SRC_OVER, 0.5f);
237
238 og2.setComposite(compo);
239 og2.setPaint(moonColor);
240 og2.fill(moon);
241
242 g.drawImage(offscreen, 0, 0, this);
243 }
244 }
A Sharper Image
1 // In file appletsawt/example/ex6/Eclipse.java
2 import java.applet.*;
3 import java.awt.*;
4 import java.awt.geom.*;
5 import java.awt.image.*;
6 import java.io.*;
7 import com.sun.image.codec.jpeg.*;
8
9 public class Eclipse extends Applet {
10
11 private Color bgColor = Color.white;
12 private Color sunColor = Color.yellow;
13 private Color moonColor = Color.black;
14
15 private Image offscreen;
16 private BufferedImage cover;
17
18 private float[] sharpKernel = {
19 0.0f, -1.0f, 0.0f,
20 -1.0f, 5.0f, -1.0f,
21 0.0f, -1.0f, 0.0f
22 };
23
24 private ConvolveOp sharpOp = new ConvolveOp(
25 new Kernel(3, 3, sharpKernel),
26 ConvolveOp.EDGE_NO_OP, null);
27
28 private int delayBetweenPaints = 50;
29 private Runner runner;
30
31 private boolean moonGoesRightToLeft = true;
32 private int moonStep = 1;
33
34 // xMoon is initialized by paint(), the first time
35 // paint() gets called. paint() knows to do this
36 // because xMoonInitialized is false, and then sets
37 // xMoonInitialized to true.
38 private boolean xMoonInitialized = false;
39 private int xMoon;
40
41 // border is the number of pixels beyond the edge
42 // of the panel that the sun circle begins
43 private static final int BORDER = 3;
44
45 public void init() {
46
47 String delayStr = getParameter("delayBetwPaints");
48
49 if (delayStr != null) {
50 try {
51
52 delayBetweenPaints = Integer.parseInt(delayStr);
53 }
54 catch (NumberFormatException e) {
55 }
56 }
57
58 String bgColorStr = getParameter("bgColor");
59
60 if (bgColorStr != null) {
61
62 try {
63
64 bgColor = Color.decode(bgColorStr);
65 }
66 catch (NumberFormatException e) {
67 }
68 }
69
70 String sunColorStr = getParameter("sunColor");
71
72 if (sunColorStr != null) {
73
74 try {
75
76 sunColor = Color.decode(sunColorStr);
77 }
78 catch (NumberFormatException e) {
79 }
80 }
81
82 String moonColorStr = getParameter("moonColor");
83
84 if (moonColorStr != null) {
85
86 try {
87
88 moonColor = Color.decode(moonColorStr);
89 }
90 catch (NumberFormatException e) {
91 }
92 }
93
94 String moonDirStr = getParameter("moonDir");
95
96 if (moonColorStr != null) {
97
98 if (moonDirStr.equalsIgnoreCase("leftToRight")) {
99
100 moonGoesRightToLeft = false;
101 }
102 }
103
104 String moonStepStr = getParameter("moonStep");
105
106 if (moonStepStr != null) {
107 try {
108
109 moonStep = Integer.parseInt(moonStepStr);
110 }
111 catch (NumberFormatException e) {
112 }
113 }
114
115 try {
116
117 FileInputStream in =
118 new FileInputStream("images/book.jpg");
119
120 try {
121 JPEGImageDecoder decoder =
122 JPEGCodec.createJPEGDecoder(in);
123 cover = decoder.decodeAsBufferedImage();
124 }
125 finally {
126 in.close();
127 }
128 }
129 catch (IOException e) {
130 }
131 }
132
133 private class Runner extends Thread {
134
135 private boolean stopRequested;
136
137 void requestStop() {
138 stopRequested = true;
139 }
140
141 public void run() {
142
143 for (;;) {
144
145 if (stopRequested) {
146 return;
147 }
148
149 if (xMoonInitialized) {
150 if (moonGoesRightToLeft) {
151 xMoon -= moonStep;
152 }
153 else {
154 xMoon += moonStep;
155 }
156 }
157
158 repaint();
159
160 try {
161 sleep(delayBetweenPaints);
162 }
163 catch (InterruptedException e) {
164 }
165 }
166 }
167 }
168
169 public synchronized void start() {
170
171 if (runner == null) {
172
173 runner = new Runner();
174 runner.start();
175 }
176 }
177
178 public synchronized void stop() {
179
180 if (runner != null) {
181
182 runner.requestStop();
183 runner = null;
184 }
185 }
186
187 public void update(Graphics g) {
188
189 paint(g);
190 }
191
192 private void checkOffscreenImage() {
193
194 Dimension d = getSize();
195 if ((offscreen == null)
196 || (offscreen.getWidth(null) != d.width)
197 || (offscreen.getHeight(null) != d.height)) {
198
199 offscreen = createImage(d.width, d.height);
200 }
201 }
202
203 public void paint(Graphics g) {
204
205 Dimension dim = getSize();
206
207 // Double buffer to reduce flicker
208 checkOffscreenImage();
209 Graphics2D og2 = (Graphics2D) offscreen.getGraphics();
210
211 og2.setColor(bgColor);
212 og2.fillRect(0, 0, dim.width, dim.height);
213
214 int diameter = dim.height;
215 if (dim.width < dim.height) {
216
217 diameter = dim.width;
218 }
219
220 diameter -= 2 * BORDER;
221 int radius = diameter / 2;
222
223 // Find sun start location
224 int xCenter = dim.width / 2;
225 int yCenter = dim.height / 2;
226
227 int xSunStart = xCenter - radius;
228 int ySunStart = yCenter - radius;
229
230 // Define gradient points
231 Point2D p1 = new Point2D.Float(xCenter, yCenter);
232 Point2D p2 = new Point2D.Float(xSunStart + (radius / 3),
233 ySunStart + (radius / 3));
234
235 // Sun should have 4 horizontal gradient cycles
236 GradientPaint gp = new GradientPaint(p1, sunColor, p2, bgColor,
237 true);
238
239 // Create the shape for the sun
240 Ellipse2D sun = new Ellipse2D.Float(xSunStart, ySunStart,
241 diameter, diameter);
242
243 og2.setPaint(gp);
244 og2.fill(sun);
245
246 // Turn antialiasing on AFTER drawing the sun
247 og2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
248 RenderingHints.VALUE_ANTIALIAS_ON);
249
250 if (!xMoonInitialized || (xMoon <= -diameter)
251 || (xMoon > dim.width)) {
252
253 if (xMoonInitialized) {
254 // Sharpen the book cover
255 cover = sharpOp.filter(cover, null);
256 }
257
258 if (moonGoesRightToLeft) {
259 xMoon = dim.width - 1;
260 }
261 else {
262 xMoon = 1 - diameter;
263 }
264 xMoonInitialized = true;
265 }
266
267 // Create the shape for the moon
268 Ellipse2D moon = new Ellipse2D.Float(xMoon, ySunStart,
269 diameter, diameter);
270
271 Composite compo = AlphaComposite.getInstance(
272 AlphaComposite.SRC_OVER, 0.5f);
273
274 og2.setComposite(compo);
275 og2.setPaint(moonColor);
276 og2.fill(moon);
277
278 int coverWidth = cover.getWidth(null);
279 int coverHeight = cover.getHeight(null);
280
281 int xCover = xMoon + radius - (coverWidth / 2);
282 int yCover = yCenter - (coverHeight / 2);
283
284 compo = AlphaComposite.getInstance(
285 AlphaComposite.SRC_OVER, 1.0f);
286
287 og2.setComposite(compo);
288 og2.clip(moon);
289 og2.drawImage(cover, xCover, yCover, null);
290
291 g.drawImage(offscreen, 0, 0, this);
292 }
293 }
A Blurred Image
1 // In file appletsawt/example/ex7/Eclipse.java
2 import java.applet.*;
3 import java.awt.*;
4 import java.awt.geom.*;
5 import java.awt.image.*;
6 import java.io.*;
7 import com.sun.image.codec.jpeg.*;
8
9 public class Eclipse extends Applet {
10
11 private Color bgColor = Color.white;
12 private Color sunColor = Color.yellow;
13 private Color moonColor = Color.black;
14
15 private Image offscreen;
16 private BufferedImage cover;
17
18 private static final float ninth = 1.0f / 9.0f;
19 private float[] blurKernel = {
20 ninth, ninth, ninth,
21 ninth, ninth, ninth,
22 ninth, ninth, ninth
23 };
24
25 private ConvolveOp blurOp = new ConvolveOp(
26 new Kernel(3, 3, blurKernel),
27 ConvolveOp.EDGE_NO_OP, null);
28
29 private int delayBetweenPaints = 50;
30 private Runner runner;
31
32 private boolean moonGoesRightToLeft = true;
33 private int moonStep = 1;
34
35 // xMoon is initialized by paint(), the first time
36 // paint() gets called. paint() knows to do this
37 // because xMoonInitialized is false, and then sets
38 // xMoonInitialized to true.
39 private boolean xMoonInitialized = false;
40 private int xMoon;
41
42 // border is the number of pixels beyond the edge
43 // of the panel that the sun circle begins
44 private static final int BORDER = 3;
45
46 public void init() {
47
48 String delayStr = getParameter("delayBetwPaints");
49
50 if (delayStr != null) {
51 try {
52
53 delayBetweenPaints = Integer.parseInt(delayStr);
54 }
55 catch (NumberFormatException e) {
56 }
57 }
58
59 String bgColorStr = getParameter("bgColor");
60
61 if (bgColorStr != null) {
62
63 try {
64
65 bgColor = Color.decode(bgColorStr);
66 }
67 catch (NumberFormatException e) {
68 }
69 }
70
71 String sunColorStr = getParameter("sunColor");
72
73 if (sunColorStr != null) {
74
75 try {
76
77 sunColor = Color.decode(sunColorStr);
78 }
79 catch (NumberFormatException e) {
80 }
81 }
82
83 String moonColorStr = getParameter("moonColor");
84
85 if (moonColorStr != null) {
86
87 try {
88
89 moonColor = Color.decode(moonColorStr);
90 }
91 catch (NumberFormatException e) {
92 }
93 }
94
95 String moonDirStr = getParameter("moonDir");
96
97 if (moonColorStr != null) {
98
99 if (moonDirStr.equalsIgnoreCase("leftToRight")) {
100
101 moonGoesRightToLeft = false;
102 }
103 }
104
105 String moonStepStr = getParameter("moonStep");
106
107 if (moonStepStr != null) {
108 try {
109
110 moonStep = Integer.parseInt(moonStepStr);
111 }
112 catch (NumberFormatException e) {
113 }
114 }
115
116 try {
117
118 FileInputStream in =
119 new FileInputStream("images/book.jpg");
120
121 try {
122 JPEGImageDecoder decoder =
123 JPEGCodec.createJPEGDecoder(in);
124 cover = decoder.decodeAsBufferedImage();
125 }
126 finally {
127 in.close();
128 }
129 }
130 catch (IOException e) {
131 }
132 }
133
134 private class Runner extends Thread {
135
136 private boolean stopRequested;
137
138 void requestStop() {
139 stopRequested = true;
140 }
141
142 public void run() {
143
144 for (;;) {
145
146 if (stopRequested) {
147 return;
148 }
149
150 if (xMoonInitialized) {
151 if (moonGoesRightToLeft) {
152 xMoon -= moonStep;
153 }
154 else {
155 xMoon += moonStep;
156 }
157 }
158
159 repaint();
160
161 try {
162 sleep(delayBetweenPaints);
163 }
164 catch (InterruptedException e) {
165 }
166 }
167 }
168 }
169
170 public synchronized void start() {
171
172 if (runner == null) {
173
174 runner = new Runner();
175 runner.start();
176 }
177 }
178
179 public synchronized void stop() {
180
181 if (runner != null) {
182
183 runner.requestStop();
184 runner = null;
185 }
186 }
187
188 public void update(Graphics g) {
189
190 paint(g);
191 }
192
193 private void checkOffscreenImage() {
194
195 Dimension d = getSize();
196 if ((offscreen == null)
197 || (offscreen.getWidth(null) != d.width)
198 || (offscreen.getHeight(null) != d.height)) {
199
200 offscreen = createImage(d.width, d.height);
201 }
202 }
203
204 public void paint(Graphics g) {
205
206 Dimension dim = getSize();
207
208 // Double buffer to reduce flicker
209 checkOffscreenImage();
210 Graphics2D og2 = (Graphics2D) offscreen.getGraphics();
211
212 og2.setColor(bgColor);
213 og2.fillRect(0, 0, dim.width, dim.height);
214
215 int diameter = dim.height;
216 if (dim.width < dim.height) {
217
218 diameter = dim.width;
219 }
220
221 diameter -= 2 * BORDER;
222 int radius = diameter / 2;
223
224 // Find sun start location
225 int xCenter = dim.width / 2;
226 int yCenter = dim.height / 2;
227
228 int xSunStart = xCenter - radius;
229 int ySunStart = yCenter - radius;
230
231 // Define gradient points
232 Point2D p1 = new Point2D.Float(xCenter, yCenter);
233 Point2D p2 = new Point2D.Float(xSunStart + (radius / 3),
234 ySunStart + (radius / 3));
235
236 // Sun should have 4 horizontal gradient cycles
237 GradientPaint gp = new GradientPaint(p1, sunColor, p2, bgColor,
238 true);
239
240 // Create the shape for the sun
241 Ellipse2D sun = new Ellipse2D.Float(xSunStart, ySunStart,
242 diameter, diameter);
243
244 og2.setPaint(gp);
245 og2.fill(sun);
246
247 // Turn antialiasing on AFTER drawing the sun
248 og2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
249 RenderingHints.VALUE_ANTIALIAS_ON);
250
251 if (!xMoonInitialized || (xMoon <= -diameter)
252 || (xMoon > dim.width)) {
253
254 if (xMoonInitialized) {
255 // Blur the book cover
256 cover = blurOp.filter(cover, null);
257 }
258
259 if (moonGoesRightToLeft) {
260 xMoon = dim.width - 1;
261 }
262 else {
263 xMoon = 1 - diameter;
264 }
265 xMoonInitialized = true;
266 }
267
268 // Create the shape for the moon
269 Ellipse2D moon = new Ellipse2D.Float(xMoon, ySunStart,
270 diameter, diameter);
271
272 Composite compo = AlphaComposite.getInstance(
273 AlphaComposite.SRC_OVER, 0.5f);
274
275 og2.setComposite(compo);
276 og2.setPaint(moonColor);
277 og2.fill(moon);
278
279 int coverWidth = cover.getWidth(null);
280 int coverHeight = cover.getHeight(null);
281
282 int xCover = xMoon + radius - (coverWidth / 2);
283 int yCover = yCenter - (coverHeight / 2);
284
285 compo = AlphaComposite.getInstance(
286 AlphaComposite.SRC_OVER, 1.0f);
287
288 og2.setComposite(compo);
289 og2.clip(moon);
290 og2.drawImage(cover, xCover, yCover, null);
291
292 g.drawImage(offscreen, 0, 0, this);
293 }
294 }
Exercises
Problem 1.
Go to the
AppletsAWT/examples/ex1
directory of the sample
code. Try out the appletviewer with this command:
appletviewer Test.html
Once you've had your fill of watching this
Flasher
applet,
close the appletviewer and edit
Test.html
. Change the
values of parameters
delayBetwPaints
,
color1
,
and
color2
to reflect your own artistic sentiments, and
try running appletviewer again.
Problem 2.
Create a new applet called
ShapeSketcher
that once per
second draws the outline of a random shape on the applet panel, placing
the shape on a random position within the bounds of the applet. The shape
should be either a
Rectangle2D
or a
Ellipse2D
,
and have width and height values that are chosen randomly. Make sure the
entire shape fits withing the bounds of the applet.
Problem 3.
Change
ShapeSketcher
so that it looks for a parameter called
delayBetwPaints
in the HTML tag and if it finds it,
sets the sleep time between paints to the value specified (in
milliseconds) in the parameter. (If it doesn't find a
delayBetwPaints
parameter, it continues to use its default
sleep time between paints of one second.)
Problem 4.
Change
ShapeSketcher
once again, this time adding a third
shape to the applet's repertoire. Using
GeneralPath
, draw
a closed triangle. You can just create a triangle of one size and use
it every time the applet decides to draw a triangle rather than a
rectangle or ellipse. So unlike the rectangle or ellipse, the triangles
won't show up in random sizes. But like rectangles and ellipses,
you should place triangles in a random position on the applet panel
each time you draw one.
Problem 5.
Copy
ShapeSketcher.java
to a new directory and rename it
ShapePainter
. Each time you draw a shape, do one more
step. Select a random color and fill the shape with that color.
Problem 6.
Use double buffering to eliminate any flicker in
ShapePainter
.
Problem 7.
Change
ShapePainter
so that instead of drawing
and painting its randomly generated shapes onto the applet panel
directly, it renders the shapes onto an
Area
which
has the same size as the applet panel, then draws the entire
Area
all at once on the applet panel. Render the shapes onto the
Area
by invoking
add()
on the
Area
.
Once you have that working, add one more
random choice to the applet. Each time you render a shape on the
Area
, pick one of four methods to invoke on
the
Area
object at random:
add()
,
subtract()
,
exlusiveOr()
, or
intersect()
.
This will cause each newly added shape to "mix" with existing shapes in
interesting ways.
Problem 8.
Change
ShapePainter
so that instead of painting the
shapes with solid colors, it paints them with a gradient that alternates
between two random colors.
Problem 9.
Find a
JPEG
or
GIF
file somewhere on the
web and figure out what it's URL is. Create yet another applet, this
time called
ImagePainter
, that displays this image on the
applet panel. Your applet should retrieve the image across the
network each time. (In other words, don't save the image file locally,
just type in the full URL of the image in your source file for
ImagePainter
.)
Problem 10.
Change
ImagePainter
so that once every 10 seconds, it
rotates the image 90 degrees clockwise. You'll have to use an
AffineTransformOp
to do the rotating. The
filter()
method will return a new image that represents the result of the
rotation, so every five seconds you'll have to replace the image
that's being displayed on the applet panel.
Problem 11.
Change
ImagePainter
one last time. This time have it
perform a dimming operation on the image each time it gets rotated.
To perform the dimming operation, you'll need to use a
RescaleOp
.
Old images never die, they just spin and fade away.
Problem 12.
If you still haven't had enough, create a new applet named
MandelbrotSet
that calculates and renders the Mandelbrot
Set in radiant colors on the applet's panel.