CS 3230 - Lab 7
Events Lab
In this week's exciting episode, you'll handle a plethora of different
events.
I'm not babying you guys with this lab as much as I did with the previous
one. I expect to see a little head scratching this time.
Specifications
Screenshot
Here's what the finished product will look like:
You will need to make two classes, Lab7, derived from
JFrame and DrawingPanel derived from JPanel. Put
both classes in a file called Lab7.java.
Lab7 class
The Lab7 class will extend JFrame and implement the
ActionListener interface.
Please see the Lab6 writeup for details
on what you should do in the main method to instantiate the frame,
and what you should do in the constructor to arrange the components in the
frame.
Handling the button click events
Clicking on the "Clear" button should clear the drawing panel (see below). Clicking on the "Quit" button should close the app.
(Hint: call System.exit(0))
To make the buttons work, do this:
- After you create new buttons (JButtons), call
setActionCommand() with a unique command string. (Hint: just
use the same string you used as the text for the button.)
- Next, call
addActionListener(this) to tell the button that the frame
will listen to its events.
- Last, override the actionPerformed() method that you inherit
from the ActionListener interface. Get the action command from
the
ActionEvent and use an if / else-if / else construct to test
which button was clicked.
You might want to look at the
UsesActionCommands.java example.
DrawingPanel class
The DrawingPanel class will extend JPanel and implement the
MouseListener,
MouseMotionListener, and
KeyListener interfaces.
Variables
You will need to declare two variables:
- A Point
variable (not Point2D) that will keep track of the last point
tracked by mouse movements. (call it lastPoint)
- An
ArrayList that will keep track of a list of lines (Line2D
objects, actually).
Constructor
- Call addMouseListener(this) to tell the panel to listen for
its own mouse events.
- Call addKeyListener(this) to tell the panel to listen for
its own keyboard events.
- Call setFocusable(true) so the panel will be able to listen
for key events.
- Do not call addMouseMotionListener() in the
constructor, we'll do that later.
- Anything else you like, i.e. setting the background color to white.
paintComponent() method
- Cast the Graphics object you receive to a
Graphics2D class, just like we did in Lab6.
- Next, iterate through ArrayList, drawing each Line2D object in there.
You might want to look at MouseTest.java or
Sketch.java for some examples of how to do
this.
Note that you are actually handling paint events by overriding the
paintComponent() method.
Overriding MouseListener methods
- mousePressed: Save the point where the mouse was
clicked by calling the getPoint() method of the
MouseEvent object you are passed and assigning the return
value to your lastPoint variable. Then call
addMouseMotionListener(this) to start listening for drag events.
- mouseReleased: Call
removeMouseMitionListener(this) to stop listening for drag
events. Next, if you have a value in your lastPoint variable
(i.e. lastPoint != null), add a line (actually, a
Line2D.Double) to the ArrayList and call the panel's
repaint() method to send a paint event. (Calling
repaint() effectively makes the paintComponent() method
get called.)
You could get by with just the above overrides, but you may want to
override the following methods to make your app work a little more
effectively.
- mouseExited: Call
removeMouseMitionListener(this) to stop listening for drag
events and assign lastPoint to null.
- mouseClicked: Add a new line to the ArrayList using
the point from the MouseEvent object for both the start and end points
(this will effectively draw a dot.) Then, call repaint(). (You
may need to offset one of the points by one to get the dot to display.)
Even if you're not interested in the other methods in the
MouseListener interface (such as mouseEntered()), you still
need to override the methods with empty bodies or the compiler will yell at
you.
Overriding MouseMotionListener methods
- mouseDragged: Add a new line to the ArrayList using
the lastPoint variable as your starting point and
MouseEvent.getPoint() as the end point. Then call
repaint().
As before, all methods inherited from the interface must be overridden,
even if you don't need to handle the event; just give them empty bodies.
Overriding KeyListener methods
- keyPressed: Get the key code from the
KeyEvent object you are passed. If it's a "Q", exit, if it's the
ESC key, clear the canvas (explained in the next
section).
Note: If you forget to call setFocusable(true) in the
Panel's constructor, it will not listen to key events. (Only the component
with the focus will receive key events.)
All other methods from the interface must be overridden with empty bodies.
You will probably want to look at Sketch.java for
an example of how to handle key events.
Convenience methods
You can get by without these, but you will probably find them useful and
they will help eliminate duplication of code.
- addLine: This method should take two Point
objects (not Point2D) and make a new Line2D.Double which
will be added to the ArrayList. Tip: You will probably want to call
repaint() in this method. It will eliminate redundant code and
make sure that you always repaint when a new line gets drawn.
Additionally, you might want to update lastPoint in here.
- clear: This method will simply
call the clear() method of the ArrayList and call repaint. You
should call this in response to the "Clear" button being pressed and the
ESC key being pressed.
Questions and Answers
What packages do I need to import?
These:
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.util.ArrayList;
Why do I have to hit TAB before ESC to clear the DrawingPanel?
The alert student will note that after you've clicked on the 'Clear'
button, then drawn on the panel, then tried to clear it again by hitting ESC,
it will not clear. This is because the 'Clear' button has the focus and is the
only control listening for kestrokes.
To cure this problem, put the line drawingPanel.grabFocus() after
you call drawingPanel.clear() in the event handler for your clear
button.
How can I use this stuff in my Application Project?
So glad you asked. You can continue making headway today on your
application project by handling various events generated by the mouse, the
keyboard, and some of the controls in your frame.
Those of you that are making a drawing program for your application
project should find this lab useful.