CSC 204 Lab 7: Graphics Using Java Swing API You have learned the ColoredRectangle class as provided in you textbook and used it in Project 2 to visualize training zone results. You may be excited, but at the same time not satisfied since the image will be gone if the window is covered up and then becomes visible again. In this lab, we will learn the “right” way to render graphics onto a window using the Java Swing API. We will also explore ways to draw (or fill) various kinds of shapes, such as circles, arcs, and polygons. Goals After doing this lab, you should be able to: Design a simple graphics application using Java classes, including JFrame and JPanel. Understand how to assign responsibilities to a few classes that are used in such a graphics application. Use the java.awt.Graphics API to render different shapes. Materials Needed Be sure you have the following on hand during the lab. This sheet Your course notebook. Java online API at java.sun.com/j2se/1.5.0/docs/api. “Anyway, let’s paint it on the window first!” – An intuitive way In Chapter 4, we learned how to create a window (using the JFrame class). We learned how to get the graphics context (using the getGraphics() method) and then paint a rectangle (using the fillRect() method) with the reference to that graphics context. A class (Smile.java) is provided in our lab folder to demonstrate the basic steps that should be enough to draw a smiling face (including eyes and a mouth). - Copy the file into a folder (e.g. Lab 7) on your desktop. Open it with your favorite editor and read the code, trying to figure out what each statement is trying to do. - Compile the file and run it. Can you see any image in the small window? Don’t be frustrated if you cannot see it. Let’s now add a few lines of code into the program, right after the line that retrieves the graphics context from the window object. 1 (You can simply uncomment three lines of code in the middle of the program.) These statements show a trick that was introduced in your text. - After saving the change, recompile and rerun the program to see what happens: can you see any image? - What happens if you use the DOS prompt to cover the small window and then move it away, such that the Smile window can be seen again. Can you see any image now? How to explain what you have observed in the last two steps? The second step is easier to understand: when the window reappears, all images once were shown need to be rendered again such that a user can see them. The window (including the title bar and the other three edges) is redrawn! But the smiling face is not, since you’ve never told the computer to do that. Your code has been executed, once, and that’s it. You didn’t ask for a second run. So it tells you that intuition didn’t work here: you should not have tried to draw the image directly. You should ask the computer (or JVM) to draw it whenever it is needed, such as when the window is first displayed or when it reappears. (We call this mechanism callback. Heard it before? “Don’t call us. We’ll call you!” We’ll see how it’s done in Java next.) The first step is a bit more complicated. What can help you for now is that the JFrame window paints images on a few layers in a predefined order: your image is painted to a layer beneath the layer call content pane that JFrame paints to blank. The right way of doing is to tell the JFrame window what you need to paint and let it add your image into its content pane. The window knows when is the right time to do it and it will then render your image on top. “Leave it with me!” – The “right” way Now we are ready to do it the right way. To start off, we need to use the object-oriented way of thinking. First we need to find out how many objects (or classes) we need to use. If we read the main method more closely, we should be able to tell that the program is trying to play two different roles: - The first four lines are trying to create a window, while - The rest of the program is trying to define how to draw the smiling face. (This may not be obvious at the first look. But you can get it easily when I tell you that I may want you to draw the face in a different location or to draw two or more faces in the same window. Project 2 serves as an example for this aspect, in which you write a class that uses some ColoredRectangle objects.) 2 So we need two classes, Smiley and ShowSmiley, one defining a smiling face and the other create a window to display the face. The Smiley class This class needs to define four instance variables, x and y for its location, and w and h for its dimension. It also needs a constructor to initialize the four instance variable, and a paint method to specify how the face is to be drawn. - A Smiley class an unfinished paint method is provided for you to work on. You can copy the last seven statements in the Smile program and modify them such that the face parts are parameterized (or expressed in terms of the four instance method). o For example, the following statement g.fillOval(20,20,60,60); should be revised as g.fillOval(x, y, w, h); (Details to be discussed during the lab session.) The ShowSmiley class This class is provided in the Lab 7 folder. It includes all the first four statements in the main method of the Smile class to create a window properly. Other added features are briefly explained as follows: - First of all, this class extends the JPanel class, which is a container class and often used as a canvas for rendering images. We need a container class since that is the way that we can add our image onto the content pane of the JFrame. (To convince yourself about the importance of the content pane, you can open Java online API: on the page for JFrame, a quote from the second paragraph reads, “The content pane provided by the root pane should, as a rule, contain all the non-menu components displayed by the JFrame.”) One way to add your image onto the content pane is to invoke the setContentPane method (of JFrame), which takes a Container object as the only parameter. - A paintComponent method is implemented, which creates a Smiley object and then invokes its paint method. The paintComponent method is to be invoked by the JFrame when it (re)paints itself. (It calls back!) A Graphics reference is provided as the only parameter to this method. It is passed to the Smiley object when its paint method is invoked: this makes sure that the smiling face is painted to the graphics context of the JPanel (used as a canvas), which is in the content pane of the window. 3 Try it your way The topics that are discussed in this lab can be used in your own practice in Project 3. You may try to do the following exercises: - Try the drawXXX methods (such as drawRect or drawOVal) with the same argument you used with the fillXXX methods and observe the differences. - Add another smiley object using parameters that you deem appropriate. You may adjust the size of the window to make more room for the new face. - Have a closer look at how arcs are rendered: change the start angle from 180 to 0 and see what happens. Does it look like a sad face now? Adjust the position of the mouth to move it downward a bit to align with the mouth on the (once) happy face. o What change to the class can display a happy/sad face conditionally? - Add a nose (a triangle shape) to the center of the facial area. You may append the following lines of code to the end of the paint method of Smiley and modify it if you feel need to. The triangle was defined as a polygon with 3 end points, which are defined with their x and y coordinates using two arrays of integers (int[]). g.setColor(Color.orange); int[] xpoints = {50, 55, 45}; int[] ypoints = {45, 55, 55}; Polygon nose = new Polygon(xpoints, ypoints, 3); g.fillPolygon(nose); - Want more fun? You may write a class to draw some pictures with basic geometrical shapes and various colors. The ShowSmiley class (or a modified version) can handle any class with a paint method. [Some examples will be given in class to inspire your imagination.] Don’t forget to show your programs to your instructor when you have some of them done. 4