2D Graphics & Java2D
2D Graphics & Java2D
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 1 / 20
2D Graphics & Java2D 7/14/2015
15 // ......
16
17 /** Constructor to setup the GUI components */
18 public SwingTemplateJPanel() {
19 setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
20 // "this" JPanel container sets layout
21 // setLayout(new ....Layout());
22
23 // Allocate the UI components
24 // .....
25
26 // "this" JPanel adds components
27 // add(....)
28
29 // Source object adds listener
30 // .....
31 }
32
33 /** Custom painting codes on this JPanel */
34 @Override
35 public void paintComponent(Graphics g) {
36 super.paintComponent(g); // paint background
37 setBackground(Color.BLACK);
38
39 // Your custom painting codes
40 // ......
41 }
42
43 /** The entry main() method */
44 public static void main(String[] args) {
45 // Run GUI codes in the Event-Dispatching thread for thread safety
46 SwingUtilities.invokeLater(new Runnable() {
47 public void run() {
48 JFrame frame = new JFrame(TITLE);
49 frame.setContentPane(new SwingTemplateJPanel());
50 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
51 frame.pack(); // "this" JFrame packs its components
52 frame.setLocationRelativeTo(null); // center the application window
53 frame.setVisible(true); // show it
54 }
55 });
56 }
57 }
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 2 / 20
2D Graphics & Java2D 7/14/2015
23 }
2.1 java.awt.Graphics2D
The core class in Java2D is the java.awt.Graphics2D. Graphics2D is a subclass of java.awt.Graphics, which extends the support
of the legacy Graphics class in rendering three groups of objects: text, vector-graphics and bitmap images. It also supports more attributes
that affect the rendering, e.g.,
Transform attribute (translation, rotation, scaling and shearing).
Pen attribute (outline of a shape) and Stroke attribute (point-size, dashing-pattern, end-cap and join decorations).
Fill attribute (interior of a shape) and Paint attribute (fill shapes with solid colors, gradients, and patterns).
Composite attribute (for overlapping shapes).
Clip attribute (display area).
Font attribute.
Graphics2D is designed as a subclass of Graphics. To use Graphcs2D context, downcast the Graphics handle g to Graphics2D in
painting methods such as paintComponent(). This works because the graphics subsystem in fact passes a Graphics2D object as the
argument when calling back the painting methods. For example,
@Override
public void paintComponent(Graphics g) { // graphics subsystem passes a Graphis2D subclass object as argument
super.paintComponent(g); // paint parent's background
Graphics2D g2d = (Graphics2D) g; // downcast the Graphics object back to Graphics2D
// Perform custom drawing using g2d handle
......
}
Besides the drawXxx() and fillXxx(), Graphics2D provides more general drawing methods which operates on Shape interface.
public abstract void draw(Shape s)
public abstract void fill(Shape s)
public abstract void clip(Shape s)
Affine transform is supported via the java.awt.geom.AffineTransform class. The Graphics2D context maintains an AffineTransform
attribute, and provides methods to change the transform attributes:
// in class java.awt.Graphics2D
public abstract void setTransform(AffineTransform at); // overwrites the current Transform in the Graphics2D context
public abstract void translate(double tx, double ty); // concatenates the current Transform with a translation transform
public abstract void rotate(double theta); // concatenates the current Transform with a rotation transform
public abstract void scale(double scaleX, double scaleY) // concatenates the current Transform with a scaling transform
public abstract void shear(double shearX, double shearY) // concatenates the current Transform with a shearing transform
Example
1 import java.awt.*;
2 import java.awt.geom.AffineTransform;
3 import javax.swing.*;
4
5 /** Test applying affine transform on vector graphics */
6 @SuppressWarnings("serial")
7 public class AffineTransformDemo extends JPanel {
8 // Named-constants for dimensions
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 3 / 20
2D Graphics & Java2D 7/14/2015
These are the steps for carrying out affine transform with a Graphics2D context:
1. Override the paintComponent(Graphics) method of the custom drawing JPanel. Downcast the Graphics object into
Graphics2D.
@Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
......
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 4 / 20
2D Graphics & Java2D 7/14/2015
2. Prepare a Shape (such as Polygon, Rectangle2D, Rectangle). The original shape shall center at (0, 0) to simplify rotation.
3. Save the current transform associated with this Graphics2D context, and restore the saved transform before exiting the method.
AffineTransform saveTransform = g2d.getTransform(); // save
....
g2d.setTransform(saveTransform); // restore
4. Allocate a new AffineTransform. Initialize to the default identity transform. Apply it to the current Graphics2D context. You can
then use the Graphics2D context to perform translation, rotation, scaling and shearing.
AffineTransform identity = new AffineTransform(); // an identity transform
g2d.setTransform(identity); // overwrites the transform associated with this Graphics2D context
g2d.translate(x, y); // translates from (0, 0) to the current (x, y) position
g2d.scale(scaleX, scaleY); // scaling
g2d.rotate(angle); // rotation clockwise about (0, 0), by angle (in radians)
g2d.shear(shearX, shearY); // shearing
Take note that successive transforms are concatenated, until it is reset (to the identity transform) or overwritten.
In the above example, the Polygon, which is originally centered at (0, 0) (shown in green), is first translated to (50, 50) and scaled up by 1.2
(in green). A loop of 5-iterations is applied to translate by (50, 5) (in blue) and rotate by 15 degrees about (0, 0) (in red). Observe that after
each transform, the axes and origin are transformed accordingly. This is especially noticeable for rotation, as the axes are no longer parallel
and perpendicular to the screen and its origin is shifted as well. The origin of the axes is set to (0, 0) by the identity transform.
Rotation
The result of rotation depends on the angle rotated, as well as its rotation center. Two methods are provided:
public abstract void rotate(theta);
public abstract void rotate(theta, anchorX, anchorY)
The first method rotates about the origin (0, 0), while the second method rotate about (anchorX, anchorY), without affecting the origin after
the rotation. Take note that after each rotation, the coordinates is rotated as well. Rotation can be made simpler, by center the shape at (0, 0)
as shown in the above example.
GeneralPath
The java.awt.geom.GeneralPath class represents a geometric path constructed from straight lines, quadratic and cubic curves. For
example,
int[] x = { -20, 0, 20, 0};
int[] y = { 20, 10, 20, -20};
GeneralPath p = new GeneralPath();
p.moveTo(x[0], y[0]);
for (int i = 1; i < x.length; ++i) {
p.lineTo(x[i], y[i]);
}
p.closePath();
g2d.translate(350, 250);
g2d.draw(p);
2.4 Point2D and its Subclasses Point, Point2D.Double and Point2D.Float (Advanced)
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 5 / 20
2D Graphics & Java2D 7/14/2015
java.awt.geom.Point2D
Point2D is an abstract class that cannot be instantiated. It declares the following abstract methods:
abstract public double getX();
abstract public double getY();
abstract public void setLocation(double x, double y);
It also defines and implemented some static methods and member methods. (Hence, it is designed as an abstract class, instead of
interface.)
// static methods
public static double distance(double x1, double y1, double x2, double y2)
public static double distanceSq(double x1, double y1, double x2, double y2)
// instance (non-static) methods
public double distance(double x, double y)
public double distanceSq(double x, double y)
public double distance(Point2D p)
public double distanceSq(Point2D p)
......
Point2D does not define any instance variable, in particular, the x and y location of the point. This is because it is not sure about the type of
x and y (which could be int, float or double). The instance variables, therefore, are left to the implementation subclasses. Three subclasses
were implemented for types of int, float and double, respectively.
Point (of int-precision) is a straight-forward implementation of inheritance and polymorphism. Point is a legacy class (since JDK 1.1) and
retrofitted when Java 2D was introduced. For higher-quality and smoother graphics (e.g., rotation), int-precision is insufficient. Java 2D,
hence, introduced float-precision and double-precision points.
Point2D.Double (for double-precision point) and Point2D.Float (for float-precision point) are, however, implemented as nested
public static subclasses inside the Point2D outer class.
Recall that nested class (or inner class) can be used for:
1. Simplifying access control: inner class can access the private variables of the enclosing outer class, as they are at the same level.
2. Keeping codes together and namespace management.
In this case, it is used for namespace management, as there is no access-control involved.
package java.awt.geom;
abstract public class Point2D { // outer class
public static class Double extend Point2D { // public static nested class and subclass
public double x;
public double y;
// Constructor
public Double(double x, double y) { this.x = x; this.y = y; }
// Provides implementation to the abstract methods
public double getX() { return x; }
public double getY() { return y; }
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 6 / 20
2D Graphics & Java2D 7/14/2015
public static class Float extend Point2D { // public static nested class and subclass
public float x;
public float y;
// Constructor
public Float(float x, float y) { this.x = x; this.y = y; }
// Provide implementation to the abstract methods
public double getX() { return x; }
public double getY() { return y; }
public void setLocation(double x, double y) {
this.x = (float)x;
this.y = (float)y;
}
// Other methods
......
}
Double and Float are static. In other words, they can be referenced via the classname as Point2D.Double and Point2D.Float, and
used directly without instantiating the outer class, just like any static variable or method (e.g., Math.PI, Math.sqrt(),
Integer.parseInt()). They are subclasses of Point2D, and thus can be upcasted to Point2D.
Point2D.Double p1 = new Point2D.Double(1.1, 2.2);
Point2D.Float p2 = new Point2D.Float(3.3f, 4.4f);
Point p3 = new Point(5, 6);
// You can upcast subclasses Point2D.Double, Point2D.Float and Point to superclass Point2D.
Point2D p4 = new Point2D.Double(1.1, 2.2);
Point2D p5 = new Point2D.Float(3.3f, 4.4f);
Point2D p6 = new Point(5, 6);
In summary, you can treat Point2D.Double and Point2D.Float as ordinary classes with a slightly longer name. They were designed as
nested class for namespace management, instead of calling them Point2DDouble and Point2DFloat.
Note: These classes were designed before JDK 1.5, which introduces generic to support passing of type.
The Shape interface also declares methods to return the bounding rectangle of this shape (again, useful in collision detection).
Rectangle getBounds() // int-precision
Rectangle2D getBounds2D() // higher precision version
The Shape interface declares a method called getPathIterator() to retrieve a PathIterator object that can be used to iterate along
the Shape boundary.
PathIterator getPathIterator(AffineTransform at)
PathIterator getPathIterator(AffineTransform at, double flatness)
The popular legacy java.awt.Polygon class was retrofitted to implement Shape interface. However, there is no Polyon2D in Java 2D,
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 7 / 20
2D Graphics & Java2D 7/14/2015
For example,
g2d.setStroke(new BasicStroke(10, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g2d.setColor(Color.CYAN);
g2d.draw(new Rectangle2D.Double(300, 50, 200, 100));
// Test dash-stroke
float[] dashPattern = {20, 5, 10, 5}; // dash, space, dash, space
g2d.setStroke(new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND,
10, dashPattern, 0));
g2d.setColor(Color.CYAN);
g2d.draw(new Rectangle2D.Double(50, 200, 200, 100));
Paint
The Graphics2D's paint attribute determines the color used to render the shape. It is set via the Graphics2D's setPaint() method. A
Paint object implements the java.awt.Paint interface. Java 2D provides many built-in Paint objects such as GradientPaint,
LinearGradientPaint, RadialGradientPaint, MultipleGradientPaint, TexturePaint, and others.
For example,
g2d.setPaint(new GradientPaint(50, 80, Color.RED, 250, 180, Color.GREEN));
// set current paint context to a GradientPaint, from (x1, y1) with color1 to (x2, y2) with color2
g2d.fill(new Rectangle2D.Double(50, 80, 200, 100));
// fill the Shap with the current paint context
Composite
[TODO] How to compose the drawing of primitive with the underlying graphics area.
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 8 / 20
2D Graphics & Java2D 7/14/2015
BufferedImage supports image filtering operations (such as convolution). The resultant image can be painted on the screen, sent to printer,
or save to an external file.
Instead of using java.io.File class to handle a disk file, it is better to use java.net.URL. URL is more flexible and can handle files from
more sources, such as disk file and JAR file (used for distributing your program). It works on application as well as applet. For example,
1 import java.awt.*;
2 import java.io.IOException;
3 import java.net.URL;
4 import javax.imageio.ImageIO;
5 import javax.swing.*;
6
7 /** Test loading an external image into a BufferedImage using ImageIO.read() */
8 @SuppressWarnings("serial")
9 public class LoadImageDemo extends JPanel {
10 // Named-constants
11 public static final int CANVAS_WIDTH = 640;
12 public static final int CANVAS_HEIGHT = 480;
13 public static final String TITLE = "Load Image Demo";
14
15 private String imgFileName = "images/duke.gif"; // relative to project root (or bin)
16 private Image img; // a BufferedImage object
17
18 /** Constructor to set up the GUI components */
19 public LoadImageDemo() {
20 // Load an external image via URL
21 URL imgUrl = getClass().getClassLoader().getResource(imgFileName);
22 if (imgUrl == null) {
23 System.err.println("Couldn't find file: " + imgFileName);
24 } else {
25 try {
26 img = ImageIO.read(imgUrl);
27 } catch (IOException ex) {
28 ex.printStackTrace();
29 }
30 }
31
32 setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
33 }
34
35 /** Custom painting codes on this JPanel */
36 @Override
37 public void paintComponent(Graphics g) {
38 super.paintComponent(g); // paint background
39 setBackground(Color.WHITE);
40 g.drawImage(img, 50, 50, null);
41 }
42
43 /** The Entry main method */
44 public static void main(String[] args) {
45 // Run the GUI codes on the Event-Dispatching thread for thread safety
46 SwingUtilities.invokeLater(new Runnable() {
47 @Override
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 9 / 20
2D Graphics & Java2D 7/14/2015
For example,
import java.awt.Toolkit;
......
Toolkit tk = Toolkit.getDefaultToolkit();
Image img = tk.getImage("images/duke.gif");
On the other hand, you can also construct an ImageIcon from an Image object via constructor:
public ImageIcon(Image image) // Construct an ImageIcon from the Image object
3.2 drawImage()
The java.awt.Graphics class declares 6 versions of drawImage() for drawing bitmap images. The subclass java.awt.Graphics2D
adds a few more.
// In class java.awt.Graphics
public abstract boolean drawImage(Image img, int x, int y, ImageObserver observer)
public abstract boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer)
public abstract boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer)
public abstract boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer)
// The img is drawn with its top-left corner at (x, y) scaled to the specified width and height
// (default to the image's width and height).
// The bgColor (background color) is used for "transparent" pixels.
public abstract boolean drawImage(Image img, int destX1, int destY1, int destX2, int destY2,
int srcX1, int srcY1, int srcX2, int srcY2, ImageObserver observer)
public abstract boolean drawImage(Image img, int destX1, int destY1, int destX2, int destY2,
int srcX1, int srcY1, int srcX2, int srcY2, Color bgcolor, ImageObserver observer)
// The img "clip" bounded by (scrX1, scrY2) and (scrX2, srcY2) is scaled and drawn from
// (destX1, destY1) to (destX2, destY2).
The coordinates involved is shown in the above diagram. The ImageObserver receives notification about the Image as it is loaded. In most
purposes, you can set it to null, or the custom drawing JPanel (via this). The ImageObserver is not needed for BufferedImage, and
shall be set to null.
Graphics2D's drawImage()
Graphics2D supports affine transform and image filtering operations on images, as follows:
// In class java.awt.Graphics2D
public abstract boolean drawImage(Image img, AffineTransform xform, ImageObserver obs)
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 10 / 20
2D Graphics & Java2D 7/14/2015
Code Example
1 import java.awt.geom.AffineTransform;
2 import javax.imageio.ImageIO;
3 import java.net.URL;
4 import java.awt.*;
5 import javax.swing.*;
6 import java.io.*;
7
8 /** Test applying affine transform on images */
9 @SuppressWarnings("serial")
10 public class ImageTransformDemo extends JPanel {
11 // Named-constants for dimensions
12 public static final int CANVAS_WIDTH = 640;
13 public static final int CANVAS_HEIGHT = 480;
14 public static final String TITLE = "Image Transform Demo";
15
16 // Image
17 private String imgFileName = "images/duke.png"; // relative to project root or bin
18 private Image img;
19 private int imgWidth, imgHeight; // width and height of the image
20 private double x = 100.0, y = 80.0; // center (x, y), with initial value
21
22 /** Constructor to set up the GUI components */
23 public ImageTransformDemo() {
24 // URL can read from disk file and JAR file
25 URL url = getClass().getClassLoader().getResource(imgFileName);
26 if (url == null) {
27 System.err.println("Couldn't find file: " + imgFileName);
28 } else {
29 try {
30 img = ImageIO.read(url);
31 imgWidth = img.getWidth(this);
32 imgHeight = img.getHeight(this);
33 } catch (IOException ex) {
34 ex.printStackTrace();
35 }
36 }
37
38 this.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
39 }
40
41 /** Custom painting codes on this JPanel */
42 @Override
43 public void paintComponent(Graphics g) {
44 super.paintComponent(g); // paint background
45 setBackground(Color.WHITE);
46
47 Graphics2D g2d = (Graphics2D) g;
48 g2d.drawImage(img, 0, 0, this); // Display with top-left corner at (0, 0)
49
50 // drawImage() does not use the current transform of the Graphics2D context
51 // Need to create a AffineTransform and pass into drawImage()
52 AffineTransform transform = new AffineTransform(); // identity transform
53 // Display the image with its center at the initial (x, y)
54 transform.translate(x - imgWidth/2, y - imgHeight/2);
55 g2d.drawImage(img, transform, this);
56 // Try applying more transform to this image
57 for (int i = 0; i < 5; ++i) {
58 transform.translate(70.0, 5.0);
59 transform.rotate(Math.toRadians(15), imgWidth/2, imgHeight/2); // about its center
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 11 / 20
2D Graphics & Java2D 7/14/2015
60 transform.scale(0.9, 0.9);
61 g2d.drawImage(img, transform, this);
62 }
63 }
64
65 /** The Entry main method */
66 public static void main(String[] args) {
67 // Run the GUI codes on the Event-Dispatching thread for thread safety
68 SwingUtilities.invokeLater(new Runnable() {
69 @Override
70 public void run() {
71 JFrame frame = new JFrame(TITLE);
72 frame.setContentPane(new ImageTransformDemo());
73 frame.pack();
74 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
75 frame.setLocationRelativeTo(null); // center the application window
76 frame.setVisible(true);
77 }
78 });
79 }
80 }
In a typical game, the actor has a (x, y) position, move at a certain speed (in pixels per move-step) and direction (in degrees), and may
rotate at a rotationSpeed (in degrees per move-step).
1 import java.awt.geom.AffineTransform;
2 import javax.imageio.ImageIO;
3 import java.net.URL;
4 import java.awt.*;
5 import javax.swing.*;
6 import java.io.*;
7
8 /** Animating image frames. Each frame has its own file */
9 @SuppressWarnings("serial")
10 public class AnimatedFramesDemo extends JPanel {
11 // Named-constants
12 static final int CANVAS_WIDTH = 640;
13 static final int CANVAS_HEIGHT = 480;
14 public static final String TITLE = "Animated Frame Demo";
15
16 private String[] imgFilenames = {
17 "images/pacman_1.png", "images/pacman_2.png", "images/pacman_3.png"};
18 private Image[] imgFrames; // array of Images to be animated
19 private int currentFrame = 0; // current frame number
20 private int frameRate = 5; // frame rate in frames per second
21 private int imgWidth, imgHeight; // width and height of the image
22 private double x = 100.0, y = 80.0; // (x,y) of the center of image
23 private double speed = 8; // displacement in pixels per move
24 private double direction = 0; // in degrees
25 private double rotationSpeed = 1; // in degrees per move
26
27 // Used to carry out the affine transform on images
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 12 / 20
2D Graphics & Java2D 7/14/2015
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 13 / 20
2D Graphics & Java2D 7/14/2015
103 setBackground(Color.WHITE);
104 Graphics2D g2d = (Graphics2D) g;
105
106 transform.setToIdentity();
107 // The origin is initially set at the top-left corner of the image.
108 // Move the center of the image to (x, y).
109 transform.translate(x - imgWidth / 2, y - imgHeight / 2);
110 // Rotate about the center of the image
111 transform.rotate(Math.toRadians(direction),
112 imgWidth / 2, imgHeight / 2);
113 // Apply the transform to the image and draw
114 g2d.drawImage(imgFrames[currentFrame], transform, null);
115 }
116
117 /** The Entry main method */
118 public static void main(String[] args) {
119 // Run the GUI codes on the Event-Dispatching thread for thread safety
120 SwingUtilities.invokeLater(new Runnable() {
121 @Override
122 public void run() {
123 JFrame frame = new JFrame(TITLE);
124 frame.setContentPane(new AnimatedFramesDemo());
125 frame.pack();
126 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
127 frame.setLocationRelativeTo(null); // center the application window
128 frame.setVisible(true);
129 }
130 });
131 }
132 }
1 import javax.imageio.ImageIO;
2 import java.net.URL;
3 import java.awt.*;
4 import javax.swing.*;
5 import java.io.*;
6
7 /** Animating image frames. All frames kept in a stripe. */
8 @SuppressWarnings("serial")
9 public class AnimatedFramesInStripe extends JPanel {
10 // Named-constants
11 static final int CANVAS_WIDTH = 640;
12 static final int CANVAS_HEIGHT = 480;
13 public static final String TITLE = "Animated Frame Demo";
14
15 private String imgFilename = "images/GhostStripe.png";
16 private int numRows, numCols, numFrames;
17 private Image img; // for the entire image stripe
18 private int currentFrame; // current frame number
19 private int frameRate = 5; // frame rate in frames per second
20 private int imgWidth, imgHeight; // width and height of the image
21 private double x = 100.0, y = 80.0; // (x,y) of the center of image
22 private double speed = 8; // displacement in pixels per move
23 private double direction = 0; // in degrees
24 private double rotationSpeed = 1; // in degrees per move
25
26 /** Constructor to set up the GUI components */
27 public AnimatedFramesInStripe() {
28 // Setup animation
29 loadImage(imgFilename, 2, 4);
30 Thread animationThread = new Thread () {
31 @Override
32 public void run() {
33 while (true) {
34 update(); // update the position and image
35 repaint(); // Refresh the display
36 try {
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 14 / 20
2D Graphics & Java2D 7/14/2015
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 15 / 20
2D Graphics & Java2D 7/14/2015
To enter fullscreen mode, use GraphicsDevice's setFullScreenWindow(JFrame). To leave the fullscreen mode and return to windowed
mode, use setFullScreenWindow(null). You should not try to setSize() or resize the window in full screen mode.
You could run your program in fullscreen (without the window's title bar) by invoking JFrame's setUndecorated(true).
There are a few ways to find out the current screen size:
// via the default Toolkit
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
int screenWidth = (int)dim.getWidth();
int screenHeight = (int)dim.getHeight();
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 16 / 20
2D Graphics & Java2D 7/14/2015
16 System.exit(1);
17 }
18
19 // Use ESC key to quit
20 addKeyListener(new KeyAdapter() {
21 @Override
22 public void keyPressed(KeyEvent e) {
23 if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
24 System.exit(0);
25 }
26 }
27 });
28
29 setContentPane(new DrawCanvas());
30 setDefaultCloseOperation(EXIT_ON_CLOSE);
31 setUndecorated(true);
32 setResizable(false);
33 defaultScreen.setFullScreenWindow(this); // full-screen mode
34 setVisible(true);
35 }
36
37 /** DrawCanvas (inner class) is a JPanel used for custom drawing */
38 private class DrawCanvas extends JPanel {
39 @Override
40 public void paintComponent(Graphics g) {
41 super.paintComponent(g);
42 setBackground(Color.BLACK);
43
44 // Paint messages
45 g.setColor(Color.YELLOW);
46 g.setFont(new Font(Font.DIALOG, Font.BOLD, 30));
47 FontMetrics fm = g.getFontMetrics();
48 String msg = "In Full-Screen mode";
49 int msgWidth = fm.stringWidth(msg);
50 int msgAscent = fm.getAscent();
51 int msgX = getWidth() / 2 - msgWidth / 2;
52 int msgY = getHeight() / 2 + msgAscent / 2;
53 g.drawString(msg, msgX, msgY);
54
55 g.setColor(Color.WHITE);
56 g.setFont(new Font(Font.DIALOG, Font.PLAIN, 18));
57 fm = g.getFontMetrics();
58 msg = "Press ESC to quit";
59 msgWidth = fm.stringWidth(msg);
60 int msgHeight = fm.getHeight();
61 msgX = getWidth() / 2 - msgWidth / 2;
62 msgY += msgHeight * 1.5;
63 g.drawString(msg, msgX, msgY);
64 }
65 }
66
67 /** The Entry main method */
68 public static void main(String[] args) {
69 // Run the GUI codes on the Event-Dispatching thread for thread safety
70 SwingUtilities.invokeLater(new Runnable() {
71 @Override
72 public void run() {
73 new FullScreenDemo();
74 }
75 });
76 }
77 }
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 17 / 20
2D Graphics & Java2D 7/14/2015
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 18 / 20
2D Graphics & Java2D 7/14/2015
87
88 @Override
89 public void componentResized(ComponentEvent e) {
90 if (!inFullScreenMode) {
91 winModeWidth = getWidth();
92 winModeHeight = getHeight();
93 }
94 }
95 });
96
97 setContentPane(new DrawCanvas());
98 setDefaultCloseOperation(EXIT_ON_CLOSE);
99 setTitle(winModeTitle);
100 setVisible(true);
101 }
102
103 /** DrawCanvas (inner class) is a JPanel used for custom drawing */
104 private class DrawCanvas extends JPanel {
105 @Override
106 public void paintComponent(Graphics g) {
107 super.paintComponent(g);
108 setBackground(Color.BLACK);
109
110 // Draw a box to indicate the borders
111 Graphics2D g2d = (Graphics2D)g;
112 g2d.setStroke(new BasicStroke(8));
113 g2d.setColor(Color.RED);
114 g2d.drawRect(0, 0, getWidth()-1, getHeight()-1);
115
116 // Paint messages
117 g.setColor(Color.YELLOW);
118 g.setFont(new Font(Font.DIALOG, Font.BOLD, 30));
119 FontMetrics fm = g.getFontMetrics();
120 String msg = inFullScreenMode ? "In Full-Screen mode" : "In Windowed mode";
121 int msgWidth = fm.stringWidth(msg);
122 int msgAscent = fm.getAscent();
123 int msgX = getWidth() / 2 - msgWidth / 2;
124 int msgY = getHeight() / 2 + msgAscent / 2;
125 g.drawString(msg, msgX, msgY);
126
127 g.setColor(Color.WHITE);
128 g.setFont(new Font(Font.DIALOG, Font.PLAIN, 18));
129 fm = g.getFontMetrics();
130 msg = "Press SPACE to toggle between Full-screen/windowed modes, ESC to quit.";
131 msgWidth = fm.stringWidth(msg);
132 int msgHeight = fm.getHeight();
133 msgX = getWidth() / 2 - msgWidth / 2;
134 msgY += msgHeight * 1.5;
135 g.drawString(msg, msgX, msgY);
136 }
137 }
138
139 /** The Entry main method */
140 public static void main(String[] args) {
141 // Run the GUI codes on the Event-Dispatching thread for thread safety
142 SwingUtilities.invokeLater(new Runnable() {
143 @Override
144 public void run() {
145 new FullScreenEscDemo();
146 }
147 });
148 }
149 }
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 19 / 20
2D Graphics & Java2D 7/14/2015
BufferredImage
other??
[TODO]
Feedback, comments, corrections, and errata can be sent to Chua Hock-Chuan (ehchua@ntu.edu.sg) | HOME
http://www.ntu.edu.sg/home/ehchua/programming/java/J8b_Game_2DGraphics.html 20 / 20