41
© 2006 Pearson Education Intro to Graphics 1 of 42 Intro to SWING • The Shape Object • Painting Shapes • Frames and Panels • Composite Shapes • Rotation • Animation • Window wrap-around

© 2006 Pearson EducationIntro to Graphics1 of 42 Intro to SWING The Shape Object Painting Shapes Frames and Panels Composite Shapes Rotation Animation

Embed Size (px)

Citation preview

© 2006 Pearson EducationIntro to Graphics 1 of 42

Intro to SWING

• The Shape Object

• Painting Shapes

• Frames and Panels

• Composite Shapes

• Rotation

• Animation

• Window wrap-around

© 2006 Pearson EducationIntro to Graphics 2 of 42

• Sun provided the Abstract Window Toolkit (AWT), a collection of classes (java files) that make displaying graphics easy for the programmer– object-oriented– reusable and extensible– but, AWT is very complex…

• for our course, relies too much on low-level processing

• Sun then released Swing on top of AWT– new and improved!– easier to use and more powerful!– some AWT classes are still in use…

• java.awt.Color• java.awt.Dimension• java.awt.Shape• and more…

A Long Long Time Ago…

© 2006 Pearson EducationIntro to Graphics 3 of 42

Let’s talk about shapes

• What is a Shape?– it is an Object, just like everything else in Java

• So it must have attributes…

– size– location

– border color– fill color

– rotation angle

• And capabilities…

– all attributes can change (mutators)– can draw itself– more to come later…

• mouse interaction• animation• window wrap-around

• How to keep track of the attributes?

© 2006 Pearson EducationIntro to Graphics 4 of 42

• Use AWT’s utility classes to store geometric information about a shape:– java.awt.geom.RectangularShape

• Class is abstract - use subclasses in practice

– all subclasses can be bound by a rectangular bounding box:• java.awt.geom.Rectangle2D.Double• java.awt.geom.RoundRectangle2D.Double• java.awt.geom.Ellipse2D.Double• java.awt.geom.Arc2D.Double

• Define your own shape class– contains a RectangularShape for geometric data

• these store Locations and Dimensions

– Other instance variables provide additional data• colors, rotation angle

RectangularShape

SizeLocation

© 2006 Pearson EducationIntro to Graphics 5 of 42

ColorShape

public abstract class ColorShape {

private java.awt.geom.RectangularShape

_shape;

public ColorShape (java.awt.geom.RectangularShape s) {

_shape = s;

}

//accessors/mutators and other //attributes to follow..

}

• Our shape contains a RectangularShape

© 2006 Pearson EducationIntro to Graphics 6 of 42

Location/Dimension

• The screen is a grid of pixels (tiny dots)– “picture elements”

• Unlike a Cartesian plane!– the origin is in the upper-left corner – the y-axis increases downward

• The location of any shape is described by the upper-left corner of it’s bounding box

Y

(0, 0)

(40, 40)

Pixel Art

shape

bounding box

location of shape

X

Y

X

© 2006 Pearson EducationIntro to Graphics 7 of 42

RectangularShape – Mutators/Accessors

• To set location and size:_shape.setFrame(xLoc, yLoc, width, height);

– use this method to initialize and reset location and size on a RectangularShape

• To get geometric data: _shape.getX();

_shape.getY();

_shape.getWidth();

_shape.getHeight();

© 2006 Pearson EducationIntro to Graphics 8 of 42

ColorShape class Accessors/Mutators

• Accessors to make RectangularShape data available to external classes: public double getX(){

return _shape.getX(); }

• Create mutators so external classes can change location and size independently:

public void setLocation (double x, double y){ // Change only x and y, preserve the width

and height _shape.setFrame(x, y,

_shape.getWidth(), _shape.getHeight());

}

public void setSize (double w, double h) { // Change only the width and height, preserve

the x and y coordinates _shape.setFrame(_shape.getX(),

_shape.getY(), w, h); }

© 2006 Pearson EducationIntro to Graphics 9 of 42

Storing Color

• additional data in Instance Variables

• Use accessors/mutators:

public void setFillColor(java.awt.Color c){_fillColor = c;

}

public java.awt.Color getFillColor(){

return _fillColor;

}

• Ditto for border color

• Or use one method to change both fill and border color at once:

public void setColor(java.awt.Color c){

_fillColor = c;

_borderColor = c;

}

© 2006 Pearson EducationIntro to Graphics 10 of 42

Color

• java.awt.Color stores color– RGB format

• Colors are determined by concentrations of Red, Green and Blue– each is given a value between 0-255– how many combinations are there?

• 16,777,216

• Basic colors come preset

• Colors can be– specify the alpha value [0-255]…– 0 = completely transparent

new java.awt.Color(0, 255, 0)

Red Green Blue

(255, 0, 0) = (0, 255, 0) = (0, 0, 255) =(200, 0, 200)=

new java.awt.Color(239, 174, 45, 200)

Alpha Value

java.awt.Color.orangejava.awt.Color.green

java.awt.Color.gray

© 2006 Pearson EducationIntro to Graphics 11 of 42

ColorShape again!

public abstract class ColorShape {

private java.awt.geom.RectangularShape

_shape;

private java.awt.Color _borderColor,

_fillColor;

public ColorShape (java.awt.geom.RectangularShape s) {

_shape = s;

// initialize attributes…

this.setLocation(50, 50);

this.setSize(100, 100);

this.setBorderColor

(java.awt.Color.black);

this.setFillColor(java.awt.Color.blue);

}

// accessors/mutators

}

© 2006 Pearson EducationIntro to Graphics 12 of 42

Painting Shapes

• Now we know what our ColorShape is…– a collection of data (geometric and non-

geometric)

• How do we paint it on the screen?

• Shapes will have a paint method, to paint themselves

• Nothing can paint without a paintbrush!

© 2006 Pearson EducationIntro to Graphics 13 of 42

Graphics

• Our brush is brilliantly named a “Graphics”– thanks, Java designers!

• Actually, use Graphics2D – Its more powerful subclass

• Think of it as a parameterized brush

• Each time ColorShape paints itself, it…

– sets the color of the brush

brush.setColor(_borderColor);

– tells brush to draw outline of a geometric shape

brush.draw(_shape);

– sets the color of the brush

brush.setColor(_fillColor);

– tells brush to fill geometric shape

brush.fill(_shape);

© 2006 Pearson EducationIntro to Graphics 14 of 42

ColorSubclass

•ColorShape is abstract…– what should the subclass do?

•ColorShape takes a RectangularShape in constructor– pass in subclass of RectangularShape

• Like so…

public class ColorRectangle extends ColorShape {

public ColorRectangle () {super(new

java.awt.geom.Rectangle2D.Double()); }}

• Same for other RectangularShapes– except for Arc2D…

• see book for details

© 2006 Pearson EducationIntro to Graphics 15 of 42

Frames

• Most Swing applications start with a Frame– it’s actually called a javax.swing.JFrame

• J is for Java

Mac OS X FrameMicrosoft Windows Frame

Fvwm (Sunlab) Frame

public class App extends javax.swing.JFrame{ public App() { super(“xterm”); this.setSize(500, 450); //size varies this.setDefaultCloseOperation(

EXIT_ON_CLOSE); //add code for top-level object this.setVisible(true); }

public static void main(String[] argv) { App app = new App(); }}

• When you draw graphics, you always need to draw onto some kind of container

- a frame, like the one above, holds containers…

© 2006 Pearson EducationIntro to Graphics 16 of 42

Panels

• JFrames hold JPanels– think of a JFrame as a window frame– think of a JPanel as a window pane

• Panels are the canvas for your program– in Swing, they are called javax.swing.JPanels– draw graphical shapes and GUI elements on a panel– Add panels to a frame, then add shapes and GUI

elements to the panels

Frame

Panel

sub-panels

© 2006 Pearson EducationIntro to Graphics 17 of 42

Drawing Panels

• Specialized panels hold specific types of objects– some hold buttons, sliders and text boxes– some hold shapes– some hold other panels

• Subclass a JPanel to specialize it– we want to specialize a JPanel to hold shapes

• To paint anything on any JPanel, you must partially override its special method:

paintComponent(Graphics g)– remember that a Graphics is our “brush”

• won’t call this method explicitly; Java does

• call paint on your shape from this method– pass the brush to your shape

• there’s one small complication…– you need to pass your shape a Graphics2D– the parameter of paintComponent is a Graphics

© 2006 Pearson EducationIntro to Graphics 18 of 42

Class Cast and Repaint

• Only Cast to another variable type when ABSOLUTELY Necessary

• Cast like so:

public void method (GenericType g){

SpecificType sub = (SpecificType) g; }

• Apply this pattern to get a Graphics2D

public void paintComponent(Graphics g){

Graphics2D brush = (Graphics2D) g;

//tell shape to paint itself }

© 2006 Pearson EducationIntro to Graphics 19 of 42

PaintComponent

• Whenever you want to execute the code in paintComponent(…), call repaint() on the JPanel instead

_drawingPanel.repaint();

• Java calls paintComponent(…) for you and also creates the brush for you

• Let’s clarify with a little animation…

© 2006 Pearson EducationIntro to Graphics 20 of 42

Repaint!

?

Someone

JPanel

paintComponent( g) { super.paintComponent(g); Graphics2D brush = (Graphics2D) g; _rectangle.paint(brush);}

Graphics

paint( brush) { brush.setColor(_borderColor); brush.draw(_shape); brush.setColor(_fillColor); brush.fill(_shape);}

Graphics2D

repaint() (In JPanel)

(In Shape)

© 2006 Pearson EducationIntro to Graphics 21 of 42

To the Drawing Panel!

• Add a rectangle to a Drawing Panel…

public class DrawingPanel extends JPanel {

private ColorRectangle _rectangle;

public DrawingPanel(){

super();

this.setBackground(java.awt.Color.white);

_rectangle = new ColorRectangle();

}

public void paintComponent (Graphics g){

super.paintComponent(g);

Graphics2D brush = (Graphics2D) g;

_rectangle.paint(brush);

}

}

• Wait! Don’t forget to set the size of the Panelthis.setPreferredSize(

new java.awt.Dimension(500, 500));

© 2006 Pearson EducationIntro to Graphics 22 of 42

Composite Shapes

• If we make an ellipse subclass…

public class ColorEllipse extends ColorShape {

public ColorEllipse () {

super(new java.awt.geom.Ellipse2D.Double());

}

}

• We can make a nice little alien:

• We could make 3 ellipses…and strategically place them in a Drawing Panel– but, how to move alien?

• have to change location of all 3 ellipses explicitly

• Or, make Alien class…

– alien class moves all 3 ellipses automatically

– can change alien without changing Drawing panel

– adding more aliens is easy!

© 2006 Pearson EducationIntro to Graphics 23 of 42

Nice Alien

• Nice Alien class contains 3 ellipses…

public class NiceAlien { private ColorEllipse _face, _ltEye, _rtEye; private java.awt.Color _faceColor, _eyeColor;

public NiceAlien () {//initializations, set size elided…

_face.setLocation(100, 100); _ltEye.setLocation(133, 120); _rtEye.setLocation(164, 120); }

public void setLocation (double x, double y) {_face.setLocation(x, y); // absolute

position_ltEye.setLocation(x+33, y+20); //relative “_rtEye.setLocation(x+64, y+20);

}

public void paint (Graphics2D brush){_face.paint(brush);_ltEye.paint(brush);_rtEye.paint(brush);

}}

_rtEye

_ltEye

_face

© 2006 Pearson EducationIntro to Graphics 24 of 42

• Rotating shapes is easy, but slightly counter-intuitive…– won’t rotate the java.awt.geom.RectangularShape

• Instead, tell brush (Graphics2D) to rotate the canvas. – canvas automatically rotates in opposite direction– paint shape, then un-rotate

Rotation

Final Product

No rotation

45˚ Rotation

© 2006 Pearson EducationIntro to Graphics 25 of 42

Rotation

• Need to store rotation angles…

– degrees are easier conceptually, but Graphics2D needs radians

– write accessors/mutators in degrees, store data in radians

public void setRotation (double degrees) {

_rotation = degrees*Math.PI/180;

}

public double getRotation(){

return _rotation*180/Math.PI;

}

• Rotate method requires:– angle of rotation (radians)– center point of shape

• subclasses of RectangularShape store center point

brush.rotate(_rotation,

_shape.getCenterX(), _shape.getCenterY());

© 2006 Pearson EducationIntro to Graphics 26 of 42

Color Shape

• Our new shape class can rotate…

public abstract class ColorShape {private java.awt.geom.RectangularShape _shape;private java.awt.Color _borderColor, _fillColor;private double _rotation;

public ColorShape (java.awt.geom.RectangularShape s) { //most of constructor elided… _rotation = 0;}

public void setRotation(double degrees){ _rotation = degrees*Math.PI/180;}

public double getRotation(){ return _rotation*180/Math.PI;

}

public void paint (Graphics2D brush){ // rotate canvas brush.rotate(_rotation,

_shape.getCenterX(), _shape.getCenterY()); brush.setColor(this.getBorderColor()); brush.draw(_shape); brush.setColor(this.getFillColor()); brush.fill(_shape);

// unrotate canvas brush.rotate(0-_rotation,

_shape.getCenterX(), _shape.getCenterY());}

}

© 2006 Pearson EducationIntro to Graphics 27 of 42

• Exactly the same as Nice Alien…

public class EvilAlien { private ColorEllipse _face, _ltEye, _rtEye; private java.awt.Color _faceColor, _eyeColor;

public EvilAlien () {//initializations, set dimensions elided…

• But rotate the eyes!

_face.setLocation(100, 100); _ltEye.setLocation(133, 120); _rtEye.setLocation(164, 120); } public void setLocation (double x, double y) { _face.setLocation(x, y); _ltEye.setLocation(x+33, y+20); _rtEye.setLocation(x+64, y+20); }

public void paint (Graphics2D brush){ _face.paint(brush); _ltEye.paint(brush); _rtEye.paint(brush); }}

Evil Alien

_ltEye.setRotation(-33); _rtEye.setRotation(33);

© 2006 Pearson EducationIntro to Graphics 28 of 42

Animation

• How do we animate characters like our aliens (e.g. move across screen)?

• As in film and video animation, create apparent motion with many small changes in position

• If you move in fast enough increments, you get smooth motion

• Same applies to size, orientation, shape change, etc…– all time-varying attributes are called “behaviors”

• How to create incremental change?– we need a timer that emits “ticks”

• We also need an object to listen for ticks from the timer and respond appropriatey

© 2006 Pearson EducationIntro to Graphics 29 of 42

• Want object to respond to clock tick

• Also want to model other types of behaviors– might want to respond to mouse click instead of

timer tick• See how to use the mouse in the next lecture

• Java generalizes such stimulus--response– actions, events, listeners– event gets generated by a source, which passes it to

a listener– listener in turn sends a message to one or more

responders

Event Model

© 2006 Pearson EducationIntro to Graphics 30 of 42

Event Model Continued

• Four-part process:

1) stimulus

2) object response

3) communication method

4) subscribing mechanism

Java mechanisms:1) event

2) actionPerformed

3) ActionEvent classevent record – record of what happened during stimulus

4) ActionListener

data-only object; Contains information about stimulus (e.g., location of mouse click)

the listening object’s (ActionListener’s) reaction to a stimulus

How are the responding object and stimulus connected?

classes implementing this interface can listen for a specific kind of event

listening object’s method; called in response to stimulus

button press, timer tick, etc.breaks flow of control

© 2006 Pearson EducationIntro to Graphics 31 of 42

Animation Revisited

• So, to get our aliens moving we need…– a timer– a class to listen for ticks

• must implement ActionListener• must define actionPerformed(ActionEvent e)

– should tell the alien to move (change location)

• Can call setLocation() on alien at each tick– with absolute x, y values

• Or, can give aliens a move() method– with relative x, y values – arbitrary movement

• gives aliens added functionality, encapsulation

• First, must know current location of alien– which ellipse determines location?

• the face; simple in this case, but can be more complicated for a more complex shape

– could make alien class subclass of ColorEllipse• advantages? disadvantages?

• Store alien’s current location with new instance variables…

© 2006 Pearson EducationIntro to Graphics 32 of 42

Alien Revisited

public class EvilAlien {

private ColorEllipse _face, _ltEye, _rtEye;

private java.awt.Color _faceColor, _eyeColor;

private double _alienX, _alienY;

//constructor elided

//accessors and mutators elided

public void setLocation (double x, double y) {

_face.setLocation(x, y);

_ltEye.setLocation(x+33, y+20);

_rtEye.setLocation(x+64, y+20);

_alienX = x;

_alienY = y;

}

public void move(double deltaX, double deltaY){

this.setLocation(_alienX+deltaX, _alienY+deltaY);

}

}

• Make the same additions to NiceAlien

moves 3 pixels right

and 2 pixels down

© 2006 Pearson EducationIntro to Graphics 33 of 42

The Design

• There are many ways to setup the stimulus-response mechanisms for animation. This is our way:

• The basic plan:– Create a Timer class with its own ActionListener “inner class”

– Have our DrawingPanel contain this Timer– On each tick of the Timer, tell the DrawingPanel– DrawingPanel decides what should move, and

then repaints itself

– Let’s see what this looks like in code!

© 2006 Pearson EducationIntro to Graphics 34 of 42

public class DrawingPanel extends JPanel {

private NiceAlien _alien1;

private EvilAlien _alien2;

private MyTimer _timer;

public DrawingPanel (){

//part of constructor elided

_timer = new MyTimer(this);

_timer.start();

}

/*

* move is called by ActionListener’s

* actionPerformed method.

*/

public void move() {

_alien1.move(3, 2);

_alien2.move(4, 5); //moves “faster”

this.repaint();

}

}

Motion Example

© 2006 Pearson EducationIntro to Graphics 35 of 42

Motion Example (Continued)

public class MyTimer extends javax.swing.Timer {

private DrawingPanel _drawingPanel;

public MyTimer(DrawingPanel panel) {

super(100, new MyMoveListener());

_drawingPanel = panel;

}

/**

* Private inner class, can only be used inside of

* MyTimer. This is standard for listener classes in

* Java.

*/

private class MyMoveListener implements java.awt.event.ActionListener {

// This class does not need a constructor

// More on this in section

public void actionPerformed(

java.awt.event.ActionEvent e) {

_drawingPanel.move();

}

}

}

ActionEvent is ignored in this case

approximate milliseconds between ticks

create a new instance of a MyMoveListener, defined below

© 2006 Pearson EducationIntro to Graphics 36 of 42

Design Tradeoff

• Why not have aliens implement ActionListener instead?

• Pro Alien as “Smart Object”:– each object knows how to animate itself– object is completely self-contained– encapsulation to the MAX!

• Pro Container:– container can pick which aliens move– easy to repaint after you move everything– more efficient as you add more shapes

© 2006 Pearson EducationIntro to Graphics 37 of 42

Window wrap-around

• What happens when the aliens reach the edge of the screen?– they disappear!!! Not very interesting.

• Shapes should wrap around the screen:

• First, we must know when the shape passes an edge…

– If so, call shape’s wrap() method• this check can occur in setLocation()

– wrap() recalculates shape’s location to fall within the bounds of the JPanel

© 2006 Pearson EducationIntro to Graphics 38 of 42

Modular Arithmetic

• If a shape is…– on a drawing panel of size 400x400– of size 20x30– at location (401, 150)

• Where should the new location be?– location: (1, 150)

• What formula would allow us to predict where the shape should be in all cases?

– HINT: use the Mod (%) Operator!!

© 2006 Pearson EducationIntro to Graphics 39 of 42

Wrap-around

• Aliens must know size of Drawing Panel– new instance variable; initialize in constructor

public class EvilAlien { private ColorEllipse _face, _ltEye, _rtEye; private java.awt.Color _faceColor, _eyeColor; private double _alienX, _alienY; private int _dpWidth, _dpHeight;

public EvilAlien(int dpWidth, int dpHeight) { _dpWidth = dpWidth; _dpHeight = dpHeight; //rest of constructor elided }

public void setLocation(double x, double y) { double newX = (x + _dpWidth) % _dpWidth; double newY = (y + _dpHeight) % _dpHeight;

_face.setLocation(newX, newY); _ltEye.setLocation(newX+33, newY+20); _rtEye.setLocation(newX+64, newY+20);_alienX = newX;_alienY = newY;

}}

• The alien’s constructor now takes two ints– how to retrieve those from drawing panel?

• know the size when creating the panel• or can call getSize() on the JPanel

© 2006 Pearson EducationIntro to Graphics 40 of 42

Wrapping up!

• You now have everything you need to produce graphics:

– Shape superclass• contains all necessary information

– non-geometric: instance variables– geometric: rectangularShape subclass

• paints itself– with a Graphics2D brush

• animates• wraps around the screen• you can subclass to make specific shapes

– Drawing Panel• subclass of JPanel• can draw shapes• sits in a JFrame

• User-interfaces are next!

– Come back and learn• buttons• sliders• layouts• and more!

© 2006 Pearson EducationIntro to Graphics 41 of 42