Some doc sites that you'll find useful:
A program can use the Swing package by including the statement:
import javax.swing.*;at the head of your file. All classes defined in Swing have an extra capital J in front. For example we will use JFrame class (whereas in awt it would simply be a Frame). We will get to the definition of a JFrame in a moment.
In Java, when you want to draw something, or build a graphical interface, you need a "place" to put things. For example you might need a place to do the drawing, another place to put buttons, another to write text to the user, etc. A JFrame is one way to do this. JFrames (and many of the other things we will learn about having to do with drawing) are examples of Components in Java.
As the name suggests we can put Components together to form more complex objects. Some components stand on their own (buttons, text areas), other are used to group/hold together components.
Component hierarchy: A GUI consists of components arranged in a hierarchy (one contained in another); for e.g. a window may contain a panel which contains a few buttons and labels, which in turn...etc. The application has a top-level container that holds all the individual components together into a window. Swing provides a few top-level containers (JFrame, JDialog, JApplet). We will be using JFrame.
Events: One of the things we will want to do with Components is to have users interact with them. To do this we need to track things like where the mouse is, when it has been clicked, if a button was clicked, etc. In Java all of these things are called events. When a class wants to pay attention to an event it needs to register as an event listener to that event. For e.g., if a class wants to be notified of the mouse events, it needs to register as a mouse listener.
In this lab we will start to learn how to use and create Components, how to put them together and create listeners to use them with. Since this is our first experience with "real" Java, and this class is not about Java graphics, we will stick to fairly simple Components (namely JFrames, JButtons, JPanels, etc).
Your finished program for this lab should have a number of basic capabilities. It should be able to draw Rectangles, Ovals, and Lines using a color chosen by the user. Essentially, you'll specify the location and size of a Rectangle, for example, by using the mouse directly. For example, to draw a Rectangle you would hit the Rectangle button, then press the mouse to select one corner of the rectangle, drag the mouse to the opposite corner of the rectangle and let go. When you let go the rectangle should appear. We will proceed, as always in pieces.
The first thing we need to do is to make a window. The simplest way to do this is to make our program extend the JFrame class.
import javax.swing.* public class MyDrawingProgram extends JFrame
Our new class will require a constructor (this is often where much of the work of an interactive graphical program takes place). Remember, the constructor is a method that is declared like this:
public MyDrawingProgram()At least that is a version of the constructor with no parameters. Usually the first line in the constructor should be a call to the constructor of the super-class (JFrame). The JFrame constructor takes a string parameter which is used as the window's title. The corresponding call would be
super("My drawing window!");
JFrames have lots of other useful methods built in that you inherit with the extends call. These include setSize(int x, int y) to set its size, and setVisible(boolean value) to either display it or hide it. One thing to be careful about - you can't actually draw anything within the constructor (afterall the JFrame is still being constructed!).
Within a frame, any drawing commands that are issued implicitly specify that the drawing takes place in the frame. This is accomplished by giving each JFrame its own graphics context. Therefore to draw in a JFrame you will need the correct Graphics context. For example to draw you would issue commands like:
//Note that these commands would come within one of your methods Graphics g = this.getGraphics(); // gets Graphics context g.drawRect(x, y, width, height); g.fillRect(x, y, width, height); g.setColor(Color.red); // change the pen color to red g.drawLine(x, y, x1, y1); g.fillOval(x, y, width, height);
All of the graphics stuff comes from java.awt. So you'll need an import statement like
import java.awt.*;which is a generally handy import statement for most any program.
For starters, try creating a program that extends the JFrame class. The constructor should call the parent constructor, size the window and show it (as a rule, the setVisible(true) command should be the last statement in a JFrame constructor). You might also draw a few items in the window. Remember, you can't draw within the constructor. This is a good chance to try out a useful feature of BlueJ. First, you can make a new method to do some drawing. Then once you have compiled your program, you can create a new object as you normally do which ought to bring up your JFrame. Now if you control-click the object (in the project window, it should be a red rectangle at the bottom) you can call individual methods for the object, including your drawing method. This is a nice way to test whether individual methods within a class work the way you want them to.
You may already have some experience dealing with the mouse from 101. In this lab we will do more of the same, but again will do this in "real" Java. You will not use the ObjectDraw library.
In many cases Java provides unimplemented class definitions in an interface. We talked about these in class, and the rest of this section is mostly a rehash of that discussion. Remember that the details of the implementation are left to the programmer (you). The reason this is useful is that the system then knows how to interact with your program even though you are writing something new. For example, it knows how to let your program know about Mouse events: since your program promises to implement all mouse functions, the mouse knows which functions to call on your program (though it will not know what exactly your methods do).
The first kind of interface that we are going to deal with is a MouseListener.
public class MyClass extends JFrame implements MouseListener
MouseListener is defined in java.awt.event, so you'll need an import like this:
import java.awt.event.*;
The MouseListener interface calls for five methods that you will have to include in your class. The signatures of these are as follows:
mouseClicked(MouseEvent e) mousePressed(MouseEvent e) mouseReleased(MouseEvent e) mouseEntered(MouseEvent e) mouseExited(MouseEvent e)
All methods required by MouseListener interface have a MouseEvent as a parameter. When the mouse is clicked (and if your object is a listener to the mouse), a MouseEvent is passed to the object. A MouseEvent actually contains much more information than a simple location, but for our purposes we'll just worry about getting the location out. MouseEvents have getX()and getY() methods.
In this lab you'll need three of the methods. The mousePressed event will be used to initiate drawing. The mouseReleased event will be used to terminate a drawing command. The mouseClicked will be used to reset the drawing window. Essentially the user is to use the mouse to draw lines, ovals, and rectangles. The mousePressed command determines the starting point of the object to be drawn, while the mouseReleased command determines its final point (therefore its height and width if appropriate). Despite the fact that you only need three of these methods you still need to define all five. The implements keyword says that you will do so.
Finally, it is not enough to implement the MouseListener. You must also make sure that you add it to the JFrame (this seems strange since it is being defined as part of the JFrame). Basically, just add the following line to your constructor
addMouseListener(this);
You've added your class as a mouse listener!
One of the issues we have to face in this program is selecting what it is we want to draw. We'll give the user choices by using JButtons. JButtons are another kind of Java component. You interact with them through the use of a listener. In this program we are going to attach our buttons to a JPanel, and then attach that JPanel to our JFrame. This might seem a bit excessive, but it is helpful to ensure that our buttons are placed nicely.
JButtons can be declared like any other variable. Once declared, the trick is to attach them to something (like a JPanel) and to define a listener, such that they respond to being pressed. To do this you'll need code very much like the following:
private JButton rectangleButton, lineButton; JPanel buttonArray; rectangleButton = new JButton("Rectangle"); lineButton = new JButton("Line"); buttonArray = new JPanel(); buttonArray.add(rectangle); buttonArray.add(line); //define what happens when pressing the rectangle button rectangleButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { drawRectangles(); } }); //define what happens when pressing the line button line.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { drawLines(); } }); //add the button panel to content panel of the frame getContentPane().add("South", buttonArray);
In the example two buttons would be created. When the user pressed the "Rectangle" button, a method called drawRectangles() would be called (it would be up to you to define this method). The last line of the code adds the JPanel to the JFrame and tells Java that the panel should appear at the bottom of the frame (you could also use the other directions). This is our first example of the Java layout manager.
For this program you should define a number of buttons in order to choose the kind of object to draw as well as its color. So, for example, the drawLines() method might set a global variable objectType to a value corresponding to a framedRect. Note: the "draw" buttons shouldn't actually draw anything, they should set some variables such that the next press and drag combination do the drawing (e.g. to draw a rectangle I would first press the Rectangle button and then I would press the mouse at one corner and release it at the far corner).
For some of the buttons you will need to be able to retrieve and set the current graphics context. An example would be
Graphics g = getGraphics(); g.setColor(Color.red);
public void paint(Graphics g)
This method is called on each component by the system and by the user:
When this method is invoked, the Graphics object parameter is pre-configured with the appropriate state for drawing on this particular component.
In general, programs should avoid placing rendering code at any
point where it might be invoked outside the scope of the paint
callback. Why? Because such code may be invoked at times when it is
not appropriate to paint -- for instance, before the component is
visible or has access to a valid Graphics object. It is not
recommended that programs invoke paint() directly. Instead,
whenever the application needs to trigger painting, it should call
Take a look at the two versions of Scribble: one does the drawing
in paint; one does the drawing in the mouse methods. Both get
the job done, but one is better.
Scribble1.java |
Scribble2.java
When it is complete, your program should work as an interactive
drawing tool. The user should be able to press buttons to select what
they want to draw, or the current drawing color. Clicking the mouse
should reset the drawing window. One way to do this is with the
clearRect(int x, int y, int width, int height) graphics
method). Anotehr one is to call repaint().
Your program should have a nice, easy to use interface. Experiment
with different layouts of the buttons, for example. Keep in mind that
you can use multiple JPanels, and that even a single
JPanel can have its own layout.
Your program must contain a main method so that I can test it from
the console.
The most frequent error in a program like this comes from not
worrying about what can go wrong. To really think like a computer
scientist you need to consider all of the things that can go wrong in
a program. For this program a common thing that can go wrong is that
the user can specify the rectangle "backwards". E.g. the bottom right
corner first, then the upper left second. Be sure that all possible
pairs of corners work.
Half of the lab grade is for functionality, the other half for
style. For max score your program should follow the OOP
(object-oriented programming) guidelines and should be well-commented.
Putting it together
Style
Possible extensions
Grading policy
The grading policy for this lab is the following:
Functionality: 60 points
Note: part of functionality is to handle various relative positions
for the mouse presses.
Style: 40 points
What to hand in