COM 1020 / COM xxxx 2003

Download Report

Transcript COM 1020 / COM xxxx 2003

2D Graphics
COM 1020
Martin Cooke
Objectives
To show how to draw in a Swingbased GUI using Java 2D
See Java2Demo in
demo/jfc/Java2D
PaintComponent
• To draw on a panel, you must override JPanel’s paintComponent
method
• JPanel is usually extended to obtain the desired behaviour:
public class MyPanel extends JPanel {
public void paintComponent (Graphics g) {
// code for drawing
}
}
Graphics and paintComponent
• paintComponent takes one argument of type Graphics.
Graphics has methods to draw lines, images and text, as well
as methods for changing the font, colour and pen style
• Every time you need to put text messages or graphics in a
panel, you need to define a new class and override
paintComponent
• paintComponent is called automatically by Java. You never
call it yourself.
• Whenever a window needs redrawing (eg the first time it is
displayed, or if it is resized, or if an occluding window is moved),
the event handler notifies the window, which then causes the
paintComponent method of all components to be executed.
• The repaint method forces a component to be repainted
Graphics and paintComponent (2)
• All drawing in Java is done through a Graphics object
• Coordinates on a graphics object are measured in pixels, and
(0,0) is the top left of the component
• Writing text is considered as a special kind of drawing and uses
the Graphics.drawString method:
g.drawString(textString,x,y);
• A class extending JPanel must also call
super.paintComponent(g);
so that the superclass does what drawing it has to (eg filling in
the background colour)
HelloWorldPanel
public class HelloWorldPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
String s = "Hello World";
// write in 18 point bold Sans Serif
Font ssb18 = new Font("SansSerif",Font.BOLD,18);
FontMetrics ssb18Metric = g.getFontMetrics(ssb18);
g.setFont(ssb18);
// place the string in the middle of the panel
Dimension dim = getSize(); // of the panel
int ws = ssb18Metric.stringWidth(s);
int fontHeight = ssb18Metric.getHeight();
int x = (dim.width - ws)/2;
int y = (dim.height - fontHeight)/2;
g.drawString(s,x,y);
}
}
HelloWorldFrame
public class HelloWorldFrame extends CentreFrame {
public HelloWorldFrame() {
setTitle("Hello World frame");
Container cpane = getContentPane();
cpane.add(new HelloWorldPanel());
}
public static void main(String[] args) {
JFrame frm = new HelloWorldFrame();
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frm.show();
}
}
Java 2D library
• Since JDK 1.0 the Graphics class had methods for drawing
lines, polygons, arcs etc. But it has rather limited capabilities.
• The J2SDK includes the Java 2D library which offers a more
powerful set of graphical operators
• To use Java 2D you need a Graphics2D object, which is a
subclass of Graphics. Methods such as PaintComponent
automatically receive a Graphics2D object, so it is safe to cast
the Graphics argument to Graphics2D
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
// can now apply all 2D stuff
}
Graphics context
The graphics context instantiated by a Graphics2D object has the following
fields, which can be got and set in the usual ways eg setPaint, setStroke
paint
Determines colour of shape
stroke
Line width, dashing, end styles
font
Can access all TrueType & Postscript Type 1 on
machine
transformation
Geometric transformation to apply to shape before
rendering (see later)
compositing
rule
Determines how colours should be combined with
existing colours on drawing surface eg opaque,
transparent
clipping shape
All rendering ops are limited to the area defined by
the clipping shape
rendering hints
Trade off between speed and quality
How to draw in 9 steps
1. Obtain graphics object
Graphics2D g2 = (Graphics2D) g;
2. Provide rendering hints
RenderingHints hints = . . .;
g2.setRenderingHints(hints);
3. Set stroke to define the kind of ‘brush’ to be used eg thickness,
dotted line, …
Stroke stroke = . . .;
g2.setStroke(stroke);
How to draw in 9 steps
4. Set paint to decide on color, tiling etc
Paint paint = . . .;
g2.setPaint(paint);
5. Set clipping region
Shape clip = . . .;
g2.setClip(clip);
6. Decide on transformation from user space to device space
AffineTransformation transform = . . .;
g2.transform(transform);
How to draw in 9 steps
7. Set a composition rule
Composite composite = . . .;
g2.setComposite(composite);
8. Create a shape
Shape shape = . . .;
9. Draw or fill the shape
g2.fill(shape)
g2.draw(shape)
How and when drawing takes place
• Creating a shape or setting methods of the graphicsContext do
not cause any drawing
• Drawing takes place when you call draw or fill
• Drawing sequence:
– Stroke
– Transform
– Clip
– Fill
– Compose
Shape classes (a partial view)
Geometric shape classes in
java.awt.geom
– Line2D, Rectangle2D
and Ellipse2D all
implement Shape
– Create the appropriate
object, then draw it using
Graphics2D.draw(Shape)
<<interface>>
Shape
RectangularShape
Line2D
Ellipse2D
Rectangle2D
DrawPanel
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
public class DrawPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
Dimension dim = getSize(null);
double leftX = dim.width/4.0;
double topY = dim.height/4.0;
double width = dim.width/2.0;
double height = dim.height/2.0;
Rectangle2D aRect = new Rectangle2D.Double(leftX,topY,width,height);
g2.draw(aRect);
Ellipse2D anEllipse = new Ellipse2D.Double();
anEllipse.setFrame(aRect);
g2.draw(anEllipse);
g2.draw(new Line2D.Double(leftX,topY,leftX+width,topY+height));
}
}
DrawPanel test
public class DrawFrame extends CentreFrame {
public DrawFrame() {
setTitle("Draw Frame");
getContentPane().add(new DrawPanel());
}
public static void main(String[] args) {
JFrame frm = new DrawFrame();
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frm.show();
}
}
Colour
• Graphics2D.setPaint sets the drawing colour
– g2.setPaint(Color.RED);
• Some colours are predefined constants, otherwise can define
using RGB values eg
– g2.setPaint(new Color(0,128,128));
• Use JPanel.setBackground and JPanel.setForeground
to set the default background and foreground (drawing) colours
respectively
• Can also apply the brighter() or darker() method to a
colour:
– c.brighter().brighter().brighter();
• To fill, use Graphics2D.fill rather than Graphics2D.draw
Fonts
Represented by instances of java.awt.Font
Font smallFont = new
Font(“Monospaced”,Font.PLAIN, 10);
Font names can be logical or physical (ie the normal name for the
font eg Arial)
Monospaced is a logical name for a font which should be
available on all platforms (usually mapped to Courier)
Other examples
Font(“Serif”, Font.BOLD, 18)
Font(“SansSerif”, Font.ITALIC, 6);
Images
Images represented by java.awt.Image
Can be static eg GIF, JPEG, PNG, …
Or dynamic eg a video stream, GIF89a animation
Image im =
Toolkit.getDefaultToolkit().getImage(“me.gif”);
g2.drawImage(im,75,50,this);
The 4th parameter is a reference to an image observer. This is used
to allow drawImage to return immediately even before the image
is completely drawn. The image observer can (optionally)
monitor the progress of the image drawing.
Lots of getImage() methods eg getImage(URL url)
Scaling to given rectangle:
drawImage(im,x1,y1,x2,y2,this);
Transforms
• Java 2D supports the notion of an affine transform (which is one
where parallel lines remain parallel after transformation eg
translate, rotate, scale, shear)
• To apply an affine transformation to any graphics object, supply
the appropriate information to the transform attribute in the
graphics context
• Simplest approach is to use one of these methods:
– Rotate by a given angle:
g2.rotate(theta)
– Scale by factors in each of x and y
g2.scale(x,y)
– Shear by given amount in x and y
– Translate by certain amount in x and y
• Alternatively, construct your own affine transform
• Transforms can be concatenated using concatenate
Not covered here
•
•
•
•
•
•
•
•
•
Complete shape primitives
Clipping
Compositing
Colour gradients
Polylines defined by general paths
Controlling rendering quality eg antialiasing
Image convolution eg sharpening, blurring
Double-buffering to prevent flicker during redraw
Printing
Summary
• Panels are interface components on which you can draw (and
they can also contain other components)
• To draw on a panel, extend JPanel and override
paintComponent which uses the Graphics parameter
• The Java 2D API is a powerful library for 2D graphics operations
Code
•
•
•
•
ButtonInPanel
HelloWorldPanel, HelloWorldFrame
DrawFrame, DrawPanel
DrawFrame2, DrawPanel2
Exercises
The Java 2D tutorial is really very good (and covers a lot of material
not covered here). You are strongly advised to browse it and check out
some of the advanced capabilities of 2D. You will need to read parts of
it to tackle the exercises below.
1.
2.
3.
4.
5.
6.
7.
8.
Consider the string “To be or not to be.” Display this text in a
panel in each of its 4 corners.
Modify 1 so that the string is produced in a different font in each
of the corners.
Modify 2 so that a different colour is used for each piece of text.
Find and load an image from a GIF file.
Repeat 4 but map the image to the size of the panel in which it is
placed.
Repeat 4 with an image defined by a URL.
Read about compositing and use it to paste an opaque label on
your image.
Redo 7 to make the label and/or image transparent.