Here are some of the methods in the Graphics class to draw shapes:
drawLine drawRectangle drawRoundRect draw3DRect drawPolygon drawPolyline drawOval drawArcThere are also corresponding fill methods. These methods have been in the Graphics class ever since JDK 1.0. The Java 2D API uses a completely different, object-oriented approach. Instead of methods, there are classes:
Line2D Rectangle2D RoundRectangle2D Ellipse2D Arc2D QuadCurve2D CubicCurve2D GeneralPath
These classes all implement the Shape interface.
Finally, the Point2D class describes a point with an x- and a y-coordinate. Points are useful to define shapes, but they aren't themselves shapes.
To draw a shape, you first create an object of a class that implements the Shape interface and then call the draw method of the Graphics2D class.
The Line2D, Rectangle2D, RoundRectangle2D, Ellipse2D, and Arc2D classes correspond to the drawLine, drawRectangle, drawRoundRect, drawOval, and drawArc methods. (The concept of a "3D rectangle" has died the death that it so richly deservedthere is no analog to the draw3DRect method.) The Java 2D API supplies two additional classes: quadratic and cubic curves. We discuss these shapes later in this section. There is no Polygon2D class. Instead, the GeneralPath class describes paths that are made up from lines, quadratic and cubic curves. You can use a GeneralPath to describe a polygon; we show you how later in this section.
Rectangle2D RoundRectangle2D Ellipse2D Arc2D
all inherit from a common superclass RectangularShape. Admittedly, ellipses and arcs are not rectangular, but they have a bounding rectangle (see Figure 7-2).
Figure 7-2. The bounding rectangle of an ellipse and an arc
Each of the classes with a name ending in "2D" has two subclasses for specifying coordinates as float or double quantities. In Volume 1, you already encountered Rectangle2D.Float and Rectangle2D.Double.
The same scheme is used for the other classes, such as Arc2D.Float and Arc2D.Double.
Internally, all graphics classes use float coordinates because float numbers use less storage space and they have sufficient precision for geometric computations. However, the Java programming language makes it a bit more tedious to manipulate float numbers. For that reason, most methods of the graphics classes use double parameters and return values. Only when constructing a 2D object must you choose between a constructor with float or double coordinates. For example,
Rectangle2D floatRect = new Rectangle2D.Float(5F, 10F, 7.5F, 15F); Rectangle2D doubleRect = new Rectangle2D.Double(5, 10, 7.5, 15);
The Xxx2D.Float and Xxx2D.Double classes are subclasses of the Xxx2D classes. After object construction, essentially no benefit accrues from remembering the subclass, and you can just store the constructed object in a superclass variable, just as in the code example.
As you can see from the curious names, the Xxx2D.Float and Xxx2D.Double classes are also inner classes of the Xxx2D classes. That is just a minor syntactical convenience, to avoid an inflation of outer class names.
Figure 7-3 shows the relationships between the shape classes. However, the Double and Float subclasses are omitted. Legacy classes from the pre-2D library are marked with a gray fill.
Figure 7-3. Relationships between the shape classes
Using the Shape Classes
You already saw how to use the Rectangle2D, Ellipse2D, and Line2D classes in Volume 1, Chapter 7. In this section, you will learn how to work with the remaining 2D shapes.
For the RoundRectangle2D shape, you specify the top-left corner, width and height, and the x- and y-dimension of the corner area that should be rounded (see Figure 7-4). For example, the call
RoundRectangle2D r = new RoundRectangle2D.Double(150, 200, 100, 50, 20, 20);
Figure 7-4. Constructing a RoundRectangle2D
produces a rounded rectangle with circles of radius 20 at each of the corners.
To construct an arc, you specify the bounding box, the start angle, the angle swept out by the arc (see Figure 7-5), and the closure type, one of Arc2D.OPEN, Arc2D.PIE, or Arc2D.CHORD.
Arc2D a = new Arc2D(x, y, width, height, startAngle, arcAngle, closureType);
Figure 7-5. Constructing an elliptical arc
Figure 7-6 illustrates the arc types.
Figure 7-6. Arc types
However, the angles are not simply given in degrees, but they are distorted such that a 45-degree angle denotes the diagonal position, even if width and height are not the same. If you draw circular arcs (for example, in a pie chart), then you don't need to worry about this. However, for elliptical arcs, be prepared for an adventure in trigonometrysee the sidebar for details.
The Java 2D API supports quadratic and cubic curves. In this chapter, we do not get into the mathematics of these curves. We suggest you get a feel for how the curves look by running the program in Example 7-1. As you can see in Figures 7-7 and 7-8, quadratic and cubic curves are specified by two end points and one or two control points. Moving the control points changes the shape of the curves.
Figure 7-7. A quadratic curve
Figure 7-8. A cubic curve
To construct quadratic and cubic curves, you give the coordinates of the end points and the control points. For example,QuadCurve2D q = new QuadCurve2D.Double(startX, startY, controlX, controlY, endX, endY); CubicCurve2D c = new CubicCurve2D.Double(startX, startY, control1X, control1Y, control2X, control2Y, endX, endY);
Specifying Angles for Elliptical Arcs The algorithm for drawing elliptical arcs uses distorted angles, which the caller must precompute. This sidebar tells you how. If you belong to the large majority of programmers who never draw elliptical arcs, just skip the sidebar. However, because the official documentation completely glosses over this topic, we thought it worth recording, to save those who need this information from a few hours of trigonometric agony. You convert actual angles to distorted angles with the following formula: distortedAngle = Math.atan2(Math.sin(angle) * width, Math.cos (angle) * height); Sometimes (such as in the example program at the end of this section), you know an end point of the arc, or another point on the line joining the center of the ellipse and that end point. In that case, first compute dx = p.getX() - center.getX(); dy = p.getY() - center.getY(); Then, the distorted angle is distortedAngle = Math.atan2(-dy * width, dx * height); (The minus sign in front of dy is necessary because in the pixel coordinate system, the y-axis points downward, which leads to angle measurements that are clockwise, but you need to supply an angle that is measured counterclockwise.) distortedAngle = Math.toDegrees(distortedAngle); The result is a value between -180 and 180. Compute both the distorted start and end angles in this way. Then, compute the difference between the two distorted angles. If either the start angle or the difference is negative, add 360. Then, supply the start angle and the angle difference to the arc constructor. Arc2D a = new Arc2D(x, y, width, height, distortedStartAngle, distortedAngleDifference, closureType); Not only is the documentation vague on the exact nature of the distortion, it is also quite misleading in calling the distorted angle difference value the "arc angle." Except for the case of a circular arc, that value is neither the actual arc angle nor its distortion. If you run the example program at the end of this section, then you can visually check that this calculation yields the correct values for the arc constructor (see Figure 7-9 on page 464). Figure 7-9. The ShapeTest programThe tangent formula is this: tan(angle) = opposite/adjacent Refer to this drawing: Where a is the adjacent side, o is the opposite side and theta is the angle. Similarly, sine and cosine are sin(ang)=o/h and cos(ang)=a/h where h is the long side:http://www.mathwords.com/s/sohcahtoa.htmMeanwhile atan (short for arc-tangent, also known as the inverse tangent) is the reverse of tan , like so:atan(opposite/adjacent) = angle Thus, if you know the values of both the opposite and adjacent sides (for example, by subtracting the object's coordinates from the mouse coordinates) you can get the value of the angle with atan .In game development though, it can happen fairly often that the adjacent side is equal to 0 (e.g. the x coordinate of a vector being 0). Remembering that tan(angle) = opposite/adjacent the potential for a disastrous divide-by-zero error should be clear. So a lot of libraries offer a function called atan2 , which lets you specify both the x and y parameters, to avoid the division by zero for you and give an angle in the right quadrant.The one-argument arctangent function does not distinguish between diametrically opposite directions. For example, the anticlockwise angle from the x-axis to the vector (1, 1), calculated in the usual way as arctan(1/1), is π/4 (radians), or 45°. However, the angle between the x-axis and the vector (−1, −1) appears, by the same method, to be arctan(−1/−1), again π/4, even though the answer clearly should be −3π/4, or −135°. The atan2 function takes into account the signs of both vector components, and places the angle in the correct quadrant. Thus, atan2(1, 1) = π/4 and atan2(−1, −1) = −3π/4. Additionally, the ordinary arctangent method breaks down when required to produce an angle of ±π/2 (or ±90°). For example, an attempt to find the angle between the x-axis and the vector(0, 1) requires evaluation of arctan(1/0), which fails on division by zero. In contrast, atan2(1, 0) gives the correct answer of π/2. When calculations are performed manually, the necessary quadrant corrections and exception handling can be done by inspection, but in computer programs it is extremely useful to have a single function that always gives an unambiguous correct result. DefinitionIn terms of the standard arctan function, whose range is (−π/2, π/2), it can be expressed as follows: Notes:
The free math library FDLIBM (Freely Distributable LIBM) available from netlib has source code showing how it implements atan2 including handling the various IEEE exceptional values. For systems without a hardware multiplier the function atan2 can be implemented in a numerically reliable manner by the CORDIC method. Thus implementations of atan(y) will probably choose to compute atan2(y,1). New words: anticlockwise: ngược chiều kim đồng hồ quadrant: góc 1/4 của hình Ellipse tangent: tiếp tuyến swept: quét |
Quadratic curves are not very flexible, and they are not commonly used in practice. Cubic curves (such as the Bezier curves drawn by the CubicCurve3D class) are, however, very common. By combining many cubic curves so that the slopes at the connection points match, you can create complex, smooth-looking curved shapes. For more information, we refer you to Computer Graphics: Principles and Practice, Second Edition in C by James D. Foley, Andries van Dam, Steven K. Feiner, et al. [Addison Wesley 1995].
You can build arbitrary sequences of line segments, quadratic curves, and cubic curves, and store them in a GeneralPath object. You specify the first coordinate of the path with the moveTo method. For example,
GeneralPath path = new GeneralPath(); path.moveTo(10, 20);
You then extend the path by calling one of the methods lineTo, quadTo, or curveTo. These methods extend the path by a line, a quadratic curve, or a cubic curve. To call lineTo, supply the end point. For the two curve methods, supply the control points, then the end point. For example,
path.lineTo(20, 30); path.curveTo(control1X, control1Y, control2X, control2Y, endX, endY);
You close the path by calling the closePath method. It draws a line back to the last moveTo.
To make a polygon, simply call moveTo to go to the first corner point, followed by repeated calls to lineTo to visit the other corner points. Finally, call closePath to close the polygon. The program in Example 7-1 shows this in more detail.
A general path does not have to be connected. You can call moveTo at any time to start a new path segment.
Finally, you can use the append method to add arbitrary Shape objects to a general path. The outline of the shape is added to the end to the path. The second parameter of the append method is true if the new shape should be connected to the last point on the path, false if it should not be connected. For example, the call
Rectangle2D r = . . .; path.append(r, false);
appends the outline of a rectangle to the path without connecting it to the existing path. But
path.append(r, true);
adds a straight line from the end point of the path to the starting point of the rectangle, and then adds the rectangle outline to the path.
The program in Example 7-1 lets you create sample paths. Figures 7-7 and 7-8 show sample runs of the program. You pick a shape maker from the combo box. The program contains shape makers for
- Straight lines;
- Arcs (showing lines for the bounding rectangle and the start and end angles, in addition to the arc itself);
- Polygons (using a GeneralPath); and
- Quadratic and cubic curves.
Use the mouse to adjust the control points. As you move them, the shape continuously repaints itself.
The program is a bit complex because it handles a multiplicity of shapes and supports dragging of the control points.
An abstract superclass ShapeMaker encapsulates the commonality of the shape maker classes. Each shape has a fixed number of control points that the user can move around. The getPointCount method returns that value. The abstract method
Shape makeShape(Point2D[] points)
computes the actual shape, given the current positions of the control points. The toString method returns the class name so that the ShapeMaker objects can simply be dumped into a JComboBox.
To enable dragging of the control points, the ShapePanel class handles both mouse and mouse motion events. If the mouse is pressed on top of a rectangle, subsequent mouse drags move the rectangle.
The majority of the shape maker classes are simpletheir makeShape methods just construct and return the requested shape. However, the ArcMaker class needs to compute the distorted start and end angles. Furthermore, to demonstrate that the computation is indeed correct, the returned shape is a GeneralPath containing the arc itself, the bounding rectangle, and the lines from the center of the arc to the angle control points (see Figure 7-9).
Example 7-1. ShapeTest.java
Example 7-1. ShapeTest.java
1. import java.awt.*; 2. import java.awt.event.*; 3. import java.awt.geom.*; 4. import java.util.*; 5. import javax.swing.*; 6. 7. /** 8. This program demonstrates the various 2D shapes. 9. */ 10. public class ShapeTest 11. { 12. public static void main(String[] args) 13. { 14. JFrame frame = new ShapeTestFrame(); 15. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 16. frame.setVisible(true); 17. } 18. } 19. 20. /** 21. This frame contains a combo box to select a shape 22. and a panel to draw it. 23. */ 24. class ShapeTestFrame extends JFrame 25. { 26. public ShapeTestFrame() 27. { 28. setTitle("ShapeTest"); 29. setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); 30. 31. final ShapePanel panel = new ShapePanel(); 32. add(panel, BorderLayout.CENTER); 33. final JComboBox comboBox = new JComboBox(); 34. comboBox.addItem(new LineMaker()); 35. comboBox.addItem(new RectangleMaker()); 36. comboBox.addItem(new RoundRectangleMaker()); 37. comboBox.addItem(new EllipseMaker()); 38. comboBox.addItem(new ArcMaker()); 39. comboBox.addItem(new PolygonMaker()); 40. comboBox.addItem(new QuadCurveMaker()); 41. comboBox.addItem(new CubicCurveMaker()); 42. comboBox.addActionListener(new 43. ActionListener() 44. { 45. public void actionPerformed(ActionEvent event) 46. { 47. ShapeMaker shapeMaker = (ShapeMaker) comboBox.getSelectedItem(); 48. panel.setShapeMaker(shapeMaker); 49. } 50. }); 51. add(comboBox, BorderLayout.NORTH); 52. panel.setShapeMaker((ShapeMaker) comboBox.getItemAt(0)); 53. } 54. 55. private static final int DEFAULT_WIDTH = 300; 56. private static final int DEFAULT_HEIGHT = 300; 57. } 58. 59. /** 60. This panel draws a shape and allows the user to 61. move the points that define it. 62. */ 63. class ShapePanel extends JPanel 64. { 65. public ShapePanel() 66. { 67. addMouseListener(new 68. MouseAdapter() 69. { 70. public void mousePressed(MouseEvent event) 71. { 72. Point p = event.getPoint(); 73. for (int i = 0; i < points.length; i++) 74. { 75. double x = points[i].getX() - SIZE / 2; 76. double y = points[i].getY() - SIZE / 2; 77. Rectangle2D r = new Rectangle2D.Double(x, y, SIZE, SIZE); 78. if (r.contains(p)) 79. { 80. current = i; 81. return; 82. } 83. } 84. } 85. 86. public void mouseReleased(MouseEvent event) 87. { 88. current = -1; 89. } 90. }); 91. addMouseMotionListener(new 92. MouseMotionAdapter() 93. { 94. public void mouseDragged(MouseEvent event) 95. { 96. if (current == -1) return; 97. points[current] = event.getPoint(); 98. repaint(); 99. } 100. }); 101. current = -1; 102. } 103. 104. /** 105. Set a shape maker and initialize it with a random 106. point set. 107. @param aShapeMaker a shape maker that defines a shape 108. from a point set 109. */ 110. public void setShapeMaker(ShapeMaker aShapeMaker) 111. { 112. shapeMaker = aShapeMaker; 113. int n = shapeMaker.getPointCount(); 114. points = new Point2D[n]; 115. for (int i = 0; i < n; i++) 116. { 117. double x = generator.nextDouble() * getWidth(); 118. double y = generator.nextDouble() * getHeight(); 119. points[i] = new Point2D.Double(x, y); 120. } 121. repaint(); 122. } 123. 124. public void paintComponent(Graphics g) 125. { 126. super.paintComponent(g); 127. if (points == null) return; 128. Graphics2D g2 = (Graphics2D) g; 129. for (int i = 0; i < points.length; i++) 130. { double x = points[i].getX() - SIZE / 2; 131. double y = points[i].getY() - SIZE / 2; 132. g2.fill(new Rectangle2D.Double(x, y, SIZE, SIZE)); 133. } 134. 135. g2.draw(shapeMaker.makeShape(points)); 136. } 137. 138. private Point2D[] points; 139. private static Random generator = new Random(); 140. private static int SIZE = 10; 141. private int current; 142. private ShapeMaker shapeMaker; 143. } 144. 145. /** 146. A shape maker can make a shape from a point set. 147. Concrete subclasses must return a shape in the makeShape 148. method. 149. */ 150. abstract class ShapeMaker 151. { 152. /** 153. Constructs a shape maker. 154. @param aPointCount the number of points needed to define 155. this shape. 156. */ 157. public ShapeMaker(int aPointCount) 158. { 159. pointCount = aPointCount; 160. } 161. 162. /** 163. Gets the number of points needed to define this shape. 164. @return the point count 165. */ 166. public int getPointCount() 167. { 168. return pointCount; 169. } 170. 171. /** 172. Makes a shape out of the given point set. 173. @param p the points that define the shape 174. @return the shape defined by the points 175. */ 176. public abstract Shape makeShape(Point2D[] p); 177. 178. public String toString() 179. { 180. return getClass().getName(); 181. } 182. 183. private int pointCount; 184. } 185. 186. /** 187. Makes a line that joins two given points. 188. */ 189. class LineMaker extends ShapeMaker 190. { 191. public LineMaker() { super(2); } 192. 193. public Shape makeShape(Point2D[] p) 194. { 195. return new Line2D.Double(p[0], p[1]); 196. } 197. } 198. 199. /** 200. Makes a rectangle that joins two given corner points. 201. */ 202. class RectangleMaker extends ShapeMaker 203. { 204. public RectangleMaker() { super(2); } 205. 206. public Shape makeShape(Point2D[] p) 207. { 208. Rectangle2D s = new Rectangle2D.Double(); 209. s.setFrameFromDiagonal(p[0], p[1]); 210. return s; 211. } 212. } 213. 214. /** 215. Makes a round rectangle that joins two given corner points. 216. */ 217. class RoundRectangleMaker extends ShapeMaker 218. { 219. public RoundRectangleMaker() { super(2); } 220. 221. public Shape makeShape(Point2D[] p) 222. { 223. RoundRectangle2D s = new RoundRectangle2D.Double(0, 0, 0, 0, 20, 20); 224. s.setFrameFromDiagonal(p[0], p[1]); 225. return s; 226. } 227. } 228. 229. /** 230. Makes an ellipse contained in a bounding box with two given 231. corner points. 232. */ 233. class EllipseMaker extends ShapeMaker 234. { 235. public EllipseMaker() { super(2); } 236. 237. public Shape makeShape(Point2D[] p) 238. { 239. Ellipse2D s = new Ellipse2D.Double(); 240. s.setFrameFromDiagonal(p[0], p[1]); 241. return s; 242. } 243. } 244. 245. /** 246. Makes an arc contained in a bounding box with two given 247. corner points, and with starting and ending angles given 248. by lines emanating from the center of the bounding box and 249. ending in two given points. To show the correctness of 250. the angle computation, the returned shape contains the arc, 251. the bounding box, and the lines. 252. */ 253. class ArcMaker extends ShapeMaker 254. { 255. public ArcMaker() { super(4); } 256. 257. public Shape makeShape(Point2D[] p) 258. { 259. double centerX = (p[0].getX() + p[1].getX()) / 2; 260. double centerY = (p[0].getY() + p[1].getY()) / 2; 261. double width = Math.abs(p[1].getX() - p[0].getX()); 262. double height = Math.abs(p[1].getY() - p[0].getY()); 263. 264. double distortedStartAngle = Math.toDegrees(Math.atan2(-(p[2].getY() - centerY) 265. * width, (p[2].getX() - centerX) * height)); 266. double distortedEndAngle = Math.toDegrees(Math.atan2(-(p[3].getY() - centerY) 267. * width, (p[3].getX() - centerX) * height)); 268. double distortedAngleDifference = distortedEndAngle - distortedStartAngle; 269. if (distortedStartAngle < 0) distortedStartAngle += 360; 270. if (distortedAngleDifference < 0) distortedAngleDifference += 360; 271. 272. Arc2D s = new Arc2D.Double(0, 0, 0, 0, 273. distortedStartAngle, distortedAngleDifference, Arc2D.OPEN); 274. s.setFrameFromDiagonal(p[0], p[1]); 275. 276. GeneralPath g = new GeneralPath(); 277. g.append(s, false); 278. Rectangle2D r = new Rectangle2D.Double(); 279. r.setFrameFromDiagonal(p[0], p[1]); 280. g.append(r, false); 281. Point2D center = new Point2D.Double(centerX, centerY); 282. g.append(new Line2D.Double(center, p[2]), false); 283. g.append(new Line2D.Double(center, p[3]), false); 284. return g; 285. } 286. } 287. 288. /** 289. Makes a polygon defined by six corner points. 290. */ 291. class PolygonMaker extends ShapeMaker 292. { 293. public PolygonMaker() { super(6); } 294. 295. public Shape makeShape(Point2D[] p) 296. { 297. GeneralPath s = new GeneralPath(); 298. s.moveTo((float) p[0].getX(), (float) p[0].getY()); 299. for (int i = 1; i < p.length; i++) 300. s.lineTo((float) p[i].getX(), (float) p[i].getY()); 301. s.closePath(); 302. return s; 303. } 304. } 305. 306. /** 307. Makes a quad curve defined by two end points and a control 308. point. 309. */ 310. class QuadCurveMaker extends ShapeMaker 311. { 312. public QuadCurveMaker() { super(3); } 313. 314. public Shape makeShape(Point2D[] p) 315. { 316. return new QuadCurve2D.Double(p[0].getX(), p[0].getY(), p[1].getX(), p[1].getY(), 317. p[2].getX(), p[2].getY()); 318. } 319. } 320. 321. /** 322. Makes a cubic curve defined by two end points and two control 323. points. 324. */ 325. class CubicCurveMaker extends ShapeMaker 326. { 327. public CubicCurveMaker() { super(4); } 328. 329. public Shape makeShape(Point2D[] p) 330. { 331. return new CubicCurve2D.Double(p[0].getX(), p[0].getY(), p[1].getX(), p[1].getY(), 332. p[2].getX(), p[2].getY(), p[3].getX(), p[3].getY()); 333. } 334. }
java.awt.geom.RoundRectangle2D.Double 1.2
- RoundRectangle2D.Double(double x, double y, double w, double h, double arcWidth, double arcHeight)constructs a round rectangle with the given bounding rectangle and arc dimensions.
Parameters:x, yTop-left corner of bounding rectanglew, hWidth and height of bounding rectanglearcWidthThe horizontal distance from the center to the end of the elliptical boundary arcarcHeightThe vertical distance from the center to the end of the elliptical boundary arc
java.awt.geom.Arc2D.Double 1.2
- Arc2D.Double(double x, double y, double w, double h, double startAngle, double arcAngle, int type)constructs an arc with the given bounding rectangle, start, and arc angle and arc type.
Parameters:x, yTop-left corner of bounding rectangle.w, hWidth and height of bounding rectangle.startAngleThe angular measurement between the x-axis and the line joining the center of the bounding rectangle with the starting point of the arc, in degrees. The angle is distorted so that an "angle" of 45° corresponds to the angle between the x-axis and the line joining the center and top-right corner of the bounding rectangle.arcAngleThe difference between the distorted end and start anglessee the sidebar on page 462. For a circular arc, this value equals the angle swept out by the arc.typeOne of Arc2D.OPEN, Arc2D.PIE, and Arc2D.CHORD
java.awt.geom.QuadCurve2D.Double 1.2
- QuadCurve2D.Double(double x1, double y1, double ctrlx, double ctrly, double x2, double y2)constructs a quadratic curve from a start point, a control point, and an end point.
Parameters:x1, y1The start pointctrlx, ctrlyThe control pointx2, y2The end points
java.awt.geom.CubicCurve2D.Double 1.2
- CubicCurve2D.Double(double x1, double y1, double ctrlx1, double ctrly1, double ctrlx2, double ctrly2, double x2, double y2)constructs a cubic curve from a start point, two control points, and an end point.
Parameters:x1, y1The start pointctrlx1, ctrly1The first control pointctrlx2, ctrly2The second control pointx2, y2The end points
java.awt.geom.GeneralPath 1.2
- GeneralPath()constructs an empty general path.
- void moveTo(float x, float y)makes (x, y) the current point, that is, the starting point of the next segment.
- void lineTo(float x, float y)
- void quadTo(float ctrlx, float ctrly, float x, float y)
- void curveTo(float ctrl1x, float ctrl1y, float ctrl2x, float ctrl2y, float x, float y)draw a line, quadratic curve, or cubic curve from the current point to the end point (x, y), and make that end point the current point.
- void append(Shape s, boolean connect)adds the outline of the given shape to the general path. If connect is TRue, the current point of the general path is connected to the starting point of the added shape by a straight line.
- void closePath()
closes the path by drawing a straight line from the current point to the first point in the path.
Core Java™ 2 Volume II - Advanced Features, Seventh Edition
0 comments:
Post a Comment