ClockAnalogView.java
1 |
|
2 |
import java.awt.Dimension; |
3 |
import java.awt.Graphics; |
4 |
import java.awt.Graphics2D; |
5 |
import java.awt.RenderingHints; |
6 |
import java.awt.geom.AffineTransform; |
7 |
import java.awt.geom.Ellipse2D; |
8 |
import java.awt.geom.GeneralPath; |
9 |
import java.util.Calendar; |
10 |
import java.util.Observable; |
11 |
import javax.swing.JComponent; |
12 |
|
13 |
/** |
14 |
* An analog clock View for the ClockModel. This View has no user inputs, so |
15 |
* no controller is required. This class implements the View interface, and |
16 |
* subclasses JComponent directly, to illustrate that not all Views need to |
17 |
* inherit from AbstractView. |
18 |
* |
19 |
* Note: it is not necessary to understand all the details of the rendering |
20 |
* of the analog clock. |
21 |
* |
22 |
* @author jvermeulen (inspired by IBM Java2D tutorial) |
23 |
*/ |
24 |
public class ClockAnalogView extends JComponent implements View { |
25 |
|
26 |
private Observable mModel; |
27 |
private Controller mController; |
28 |
|
29 |
int mHour; |
30 |
int mMinute; |
31 |
int mSecond; |
32 |
|
33 |
ClockAnalogView(Observable model, Controller controller) { |
34 |
mModel = model; |
35 |
mController = controller; |
36 |
} |
37 |
|
38 |
@Override |
39 |
public void setController(Controller controller) { |
40 |
mController = controller; |
41 |
} |
42 |
|
43 |
@Override |
44 |
public Controller getController() { |
45 |
return mController; |
46 |
} |
47 |
|
48 |
@Override |
49 |
public void setModel(Observable model) { |
50 |
mModel = model; |
51 |
} |
52 |
|
53 |
@Override |
54 |
public Observable getModel() { |
55 |
return mModel; |
56 |
} |
57 |
|
58 |
@Override |
59 |
public Controller defaultController(Observable model) { |
60 |
return null; |
61 |
} |
62 |
|
63 |
@Override |
64 |
public void update(Observable o, Object info) { |
65 |
// Cast info to ClockUpdate type. |
66 |
ClockUpdate clockInfo = (ClockUpdate) info; |
67 |
|
68 |
// Store hour, minute, second for repainting. |
69 |
mHour = clockInfo.getHour()+5; // +5 Geeft een latere tijdzone weer. Dit is namelijk opdracht 3. |
70 |
mMinute = clockInfo.getMinute(); |
71 |
mSecond = clockInfo.getSecond(); |
72 |
|
73 |
// Using a little trigonometry, set the transforms to rotate |
74 |
// each hand into the proper position. Center the rotation |
75 |
// around the pivot point (50, 50) instead of the origin |
76 |
hourTransform.setToRotation(((double) mHour) * |
77 |
(Math.PI / 6.0), 50, 50); |
78 |
minuteTransform.setToRotation(((double) mMinute) * |
79 |
(Math.PI / 30.0), 50, 50); |
80 |
secondTransform.setToRotation(((double) mSecond) * |
81 |
(Math.PI / 30.0), 50, 50); |
82 |
|
83 |
repaint(); |
84 |
} |
85 |
|
86 |
|
87 |
/** |
88 |
* Sets this components preferred size to 150x150. |
89 |
* @return |
90 |
*/ |
91 |
@Override |
92 |
public Dimension getPreferredSize() { |
93 |
return new Dimension(100, 100); |
94 |
} |
95 |
|
96 |
// Create a shape for the face of the clock |
97 |
protected static Ellipse2D face = new Ellipse2D.Float(3, 3, 94, 94); |
98 |
|
99 |
// Create a path that represents a tick mark |
100 |
protected static GeneralPath tick = new GeneralPath(); |
101 |
static // http://www.jusfortechies.com/java/core-java/static-blocks.php |
102 |
{ |
103 |
tick.moveTo(100, 100); |
104 |
tick.moveTo(49, 0); |
105 |
tick.lineTo(51, 0); |
106 |
tick.lineTo(51, 6); |
107 |
tick.lineTo(49, 6); |
108 |
tick.lineTo(49, 0); |
109 |
} |
110 |
|
111 |
// Create a cool hour hand |
112 |
protected static GeneralPath hourHand = new GeneralPath(); |
113 |
static |
114 |
{ |
115 |
hourHand.moveTo(50, 15); |
116 |
hourHand.lineTo(53, 50); |
117 |
hourHand.lineTo(50, 53); |
118 |
hourHand.lineTo(47, 50); |
119 |
hourHand.lineTo(50, 15); |
120 |
} |
121 |
|
122 |
// Create a cool minute hand |
123 |
protected static GeneralPath minuteHand = new GeneralPath(); |
124 |
static |
125 |
{ |
126 |
minuteHand.moveTo(50, 2); |
127 |
minuteHand.lineTo(53, 50); |
128 |
minuteHand.lineTo(50, 58); |
129 |
minuteHand.lineTo(47, 50); |
130 |
minuteHand.lineTo(50, 2); |
131 |
} |
132 |
|
133 |
// And a cool second hand |
134 |
protected static GeneralPath secondHand = new GeneralPath(); |
135 |
static |
136 |
{ |
137 |
secondHand.moveTo(49, 5); |
138 |
secondHand.lineTo(51, 5); |
139 |
secondHand.lineTo(51, 62); |
140 |
secondHand.lineTo(49, 62); |
141 |
secondHand.lineTo(49, 5); |
142 |
} |
143 |
|
144 |
// Create some colors for the pieces of the clock |
145 |
protected static Color faceColor = new Color(220, 220, 220); |
146 |
protected static Color hourColor = Color.red.darker(); |
147 |
protected static Color minuteColor = Color.blue.darker(); |
148 |
protected static Color secondColor = new Color(180, 180, 0); |
149 |
protected static Color pinColor = Color.gray.brighter(); |
150 |
|
151 |
// Create circles for the pivot and center pin |
152 |
protected Ellipse2D pivot = new Ellipse2D.Float(47, 47, 6, 6); |
153 |
protected Ellipse2D centerPin = new Ellipse2D.Float(49, 49, 2, 2); |
154 |
|
155 |
|
156 |
// Create three transforms that center around the pivot point |
157 |
protected AffineTransform hourTransform = |
158 |
AffineTransform.getRotateInstance(0, 50, 50); |
159 |
protected AffineTransform minuteTransform = |
160 |
AffineTransform.getRotateInstance(0, 50, 50); |
161 |
protected AffineTransform secondTransform = |
162 |
AffineTransform.getRotateInstance(0, 50, 50); |
163 |
|
164 |
// Create a timer that fires once a second and a Calendar |
165 |
// instance for getting the time values |
166 |
// protected Timer timer = new Timer(1000, this); |
167 |
protected Calendar calendar = Calendar.getInstance(); |
168 |
|
169 |
// This is an alternative to creating a UI delegate. Since JPanel's |
170 |
// paint() method only paints the border and backgound, we can just |
171 |
// override the paint method of the component to do the graphics. |
172 |
public void paint(Graphics g) |
173 |
{ |
174 |
// Call the superclass first to paint the border (if one is assigned) |
175 |
super.paint(g); |
176 |
|
177 |
|
178 |
// Get the graphics context and turn on anti-aliasing |
179 |
Graphics2D g2 = (Graphics2D) g; |
180 |
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, |
181 |
RenderingHints.VALUE_ANTIALIAS_ON); |
182 |
|
183 |
// Set the paint for the clock face and fill it in |
184 |
g2.setPaint(faceColor); |
185 |
g2.fill(face); |
186 |
|
187 |
// Set the paint to black and draw the clock's outline |
188 |
g2.setPaint(Color.black); |
189 |
g2.draw(face); |
190 |
|
191 |
// Fill in the 12 ticks around the face of the clock |
192 |
for (double p = 0.0; p < 12.0; p += 1.0) |
193 |
{ |
194 |
// This is probably terribly inefficient and should be |
195 |
// done statically or in the constructor - draw the |
196 |
// tick as a transformed shape that is rotated. |
197 |
g2.fill(tick.createTransformedShape( |
198 |
AffineTransform.getRotateInstance((Math.PI / 6.0) * p, |
199 |
50, 50))); |
200 |
} |
201 |
|
202 |
// Set the paint and draw the hour hand. It is lowest in the |
203 |
// 'z-order' so will appear underneath the other hands. Notice |
204 |
// how each hand is transformed by a different <AffineTransform>. |
205 |
g2.setPaint(hourColor); |
206 |
g2.fill(hourHand.createTransformedShape(hourTransform)); |
207 |
|
208 |
// Set the paint and draw the minute hand, the second hand, |
209 |
// the pivot and the center pin |
210 |
g2.setPaint(minuteColor); |
211 |
g2.fill(minuteHand.createTransformedShape(minuteTransform)); |
212 |
g2.setPaint(secondColor); |
213 |
g2.fill(secondHand.createTransformedShape(secondTransform)); |
214 |
g2.fill(pivot); |
215 |
g2.setPaint(pinColor); |
216 |
g2.fill(centerPin); |
217 |
} |
218 |
} |
219 |