Most of the graphics you have seen to this point did not vary each time you executed the program. However, Exercise 6.2 asked you to create a program that generated shapes and colors at random. In that exercise, the drawing changed every time the system called paintComponent to redraw the panel. To create a more consistent drawing that remains the same each time it is drawn, we must store information about the displayed shapes so that we can reproduce them exactly each time the system calls paintComponent.
To do this, we will create a set of shape classes that store information about each shape. We will make these classes "smart" by allowing objects of these classes to draw themselves if provided with a Graphics object. Figure 8.21 declares class MyLine, which has all these capabilities.
Figure 8.21. MyLine class represents a line.
1 // Fig. 8.21: MyLine.java 2 // Declaration of class MyLine. 3 import java.awt.Color; 4 import java.awt.Graphics; 5 6 public class MyLine 7 { 8 private int x1; // x coordinate of first endpoint 9 private int y1; // y coordinate of first endpoint 10 private int x2; // x coordinate of second endpoint 11 private int y2; // y coordinate of second endpoint 12 private Color myColor; // color of this shape 13 14 // constructor with input values 15 public MyLine( int x1, int y1, int x2, int y2, Color color ) 16 { 17 this.x1 = x1; // set x coordinate of first endpoint 18 this.y1 = y1; // set y coordinate of first endpoint 19 this.x2 = x2; // set x coordinate of second endpoint 20 this.y2 = y2; // set y coordinate of second endpoint 21 myColor = color; // set the color 22 } // end MyLine constructor 23 24 // Draw the line in the specified color 25 public void draw( Graphics g ) 26 { 27 g.setColor( myColor ); 28 g.drawLine( x1, y1, x2, y2 ); 29 } // end method draw 30 } // end class MyLine |
Class MyLine imports Color and Graphics (lines 34). Lines 811 declare instance variables for the coordinates needed to draw a line, and line 12 declares the instance variable that stores the color of the line. The constructor at lines 1522 takes five parameters, one for each instance variable that it initializes. Method draw at lines 2529 requires a Graphics object and uses it to draw the line in the proper color and at the proper coordinates.
In Fig. 8.22, we declare class DrawPanel, which will generate random objects of class MyLine. Line 12 declares a MyLine array to store the lines to draw. Inside the constructor (lines 1537), line 17 sets the background color to Color.WHITE. Line 19 creates the array with a random length between 5 and 9. The loop at lines 2236 creates a new MyLine for every element in the array. Lines 2528 generate random coordinates for each line's endpoints, and lines 3132 generate a random color for the line. Line 35 creates a new MyLine object with the randomly generated values and stores it in the array.
Figure 8.22. Creating random MyLine objects.
1 // Fig. 8.22: DrawPanel.java 2 // Program that uses class MyLine 3 // to draw random lines. 4 import java.awt.Color; 5 import java.awt.Graphics; 6 import java.util.Random; 7 import javax.swing.JPanel; 8 9 public class DrawPanel extends JPanel 10 { 11 private Random randomNumbers = new Random(); 12 private MyLine lines[]; // array of lines 13 14 // constructor, creates a panel with random shapes 15 public DrawPanel() 16 { 17 setBackground( Color.WHITE ); 18 19 lines = new MyLine[ 5 + randomNumbers.nextInt( 5 ) ]; 20 21 // create lines 22 for ( int count = 0; count < lines.length; count++ ) 23 { 24 // generate random coordinates 25 int x1 = randomNumbers.nextInt( 300 ); 26 int y1 = randomNumbers.nextInt( 300 ); 27 int x2 = randomNumbers.nextInt( 300 ); 28 int y2 = randomNumbers.nextInt( 300 ); 29 30 // generate a random color 31 Color color = new Color( randomNumbers.nextInt( 256 ), 32 randomNumbers.nextInt( 256 ), randomNumbers.nextInt( 256 ) ); 33 34 // add the line to the list of lines to be displayed 35 lines[ count ] = new MyLine( x1, y1, x2, y2, color ); 36 } // end for 37 } // end DrawPanel constructor 38 39 // for each shape array, draw the individual shapes 40 public void paintComponent( Graphics g ) 41 { 42 super.paintComponent( g ); 43 44 // draw the lines 45 for ( MyLine line : lines ) 46 line.draw( g ); 47 } // end method paintComponent 48 } // end class DrawPanel |
Method paintComponent iterates through the MyLine objects in array lines using an enhanced for statement (lines 4546). Each iteration calls the draw method of the current MyLine object and passes it the Graphics object for drawing on the panel. Class TestDraw in Fig. 8.23 sets up a new window to display our drawing. Since we are setting the coordinates for the lines only once in the constructor, the drawing does not change if paint-Component is called to refresh the drawing on the screen.
Figure 8.23. Creating JFrame to display DrawPanel.
1 // Fig. 8.23: TestDraw.java 2 // Test application to display a DrawPanel. 3 import javax.swing.JFrame; 4 5 public class TestDraw 6 { 7 public static void main( String args[] ) 8 { 9 DrawPanel panel = new DrawPanel(); 10 JFrame application = new JFrame(); 11 12 application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 13 application.add( panel ); 14 application.setSize( 300, 300 ); 15 application.setVisible( true ); 16 } // end main 17 } // end class TestDraw |
GUI and Graphics Case Study Exercise
8.1 |
Extend the program in Fig. 8.21Fig. 8.23 to randomly draw rectangles and ovals. Create classes MyRectangle and MyOval. Both of these classes should include x1, y1, x2, y2 coordinates, a color and a boolean flag to determine whether the shape is a filled shape. Declare a constructor in each class with arguments for initializing all the instance variables. To help draw rectangles and ovals, each class should provide methods getUpperLeftX, getUpperLeftY, getWidth and getHeight that calculate the upper-left x-coordinate, upper-left y-coordinate, width and height, respectively. The upper-left x-coordinate is the smaller of the two x-coordinate values, the upper-left y-coordinate is the smaller of the two y-coordinate values, the width is the absolute value of the difference between the two x-coordinate values, and the height is the absolute value of the difference between the two y-coordinate values. Class DrawPanel, which extends JPanel and handles the creation of the shapes, should declare three arrays, one for each shape type. The length of each array should be a random number between 1 and 5. The constructor of class DrawPanel will fill each of the arrays with shapes of random position, size, color and fill. In addition, modify all three shape classes to include the following:
|
Introduction to Computers, the Internet and the World Wide Web
Introduction to Java Applications
Introduction to Classes and Objects
Control Statements: Part I
Control Statements: Part 2
Methods: A Deeper Look
Arrays
Classes and Objects: A Deeper Look
Object-Oriented Programming: Inheritance
Object-Oriented Programming: Polymorphism
GUI Components: Part 1
Graphics and Java 2D™
Exception Handling
Files and Streams
Recursion
Searching and Sorting
Data Structures
Generics
Collections
Introduction to Java Applets
Multimedia: Applets and Applications
GUI Components: Part 2
Multithreading
Networking
Accessing Databases with JDBC
Servlets
JavaServer Pages (JSP)
Formatted Output
Strings, Characters and Regular Expressions
Appendix A. Operator Precedence Chart
Appendix B. ASCII Character Set
Appendix C. Keywords and Reserved Words
Appendix D. Primitive Types
Appendix E. (On CD) Number Systems
Appendix F. (On CD) Unicode®
Appendix G. Using the Java API Documentation
Appendix H. (On CD) Creating Documentation with javadoc
Appendix I. (On CD) Bit Manipulation
Appendix J. (On CD) ATM Case Study Code
Appendix K. (On CD) Labeled break and continue Statements
Appendix L. (On CD) UML 2: Additional Diagram Types
Appendix M. (On CD) Design Patterns
Appendix N. Using the Debugger
Inside Back Cover