Java Custom Graphics Programming Guide
Java Custom Graphics Programming Guide
This chapter shows you how you can paint your own custom 3.3 [Link]
drawing (such as graphs, charts, drawings and, in particular, 4. Example 1: Moving an Object via Key/Button
computer games) because you cannot find standard GUI 5. Example 2: Moving Sprites
components that meets your requirements. I shall stress that 6. Example 3: Paint
you should try to reuse the standard GUI components as far as 7. Drawing Images
possible and leave custom graphics as the last resort. 7.1 [Link]
Nonetheless, custom graphics is crucial in game programming. 7.2 Graphics Class' drawImage()
Read "Swing Tutorial" trail "Performing Custom Painting". 8. Animation
8.1 Animation using [Link]
8.2 Animation using a new Thread
1. The [Link] Class: 9. (Advanced) A Closer Look at repaint()
Graphics Context and Custom
Painting
A graphics context provides the capabilities of drawing on the screen. The graphics context maintains states
such as the color and font used in drawing, as well as interacting with the underlying operating system to
perform the drawing. In Java, custom painting is done via the [Link] class, which manages
a graphics context, and provides a set of device-independent methods for drawing texts, figures and images
on the screen on different platforms.
The [Link] is an abstract class, as the actual act of drawing is system-dependent and
device-dependent. Each operating platform will provide a subclass of Graphics to perform the actual
drawing under the platform, but conform to the specification defined in Graphics.
1 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
// Drawing lines:
drawLine(int x1, int y1, int x2, int y2);
drawPolyline(int[] xPoints, int[] yPoints, int numPoint);
These drawing methods is illustrated below. The drawXxx() methods draw the outlines; while fillXxx()
methods fill the internal. Shapes with negative width and height will not be painted. The drawImage()
will be discussed later.
2 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
// Set/Get the current clip area. Clip area shall be rectangular and no rendering is performed outsid
void setClip(int xTopLeft, int yTopLeft, int width, int height)
void setClip(Shape rect)
public abstract void clipRect(int x, int y, int width, int height) // intersects the current clip wit
3 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
4 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
1 import [Link].*;
2 import [Link].*;
3
4 /** Custom Drawing Code Template */
5 @SuppressWarnings("serial")
6 public class CGTemplate extends JFrame { // Graphics application extends JFrame
7 // Named‐constants for dimensions
8 public static final int CANVAS_WIDTH = 640;
9 public static final int CANVAS_HEIGHT = 480;
10
11 private DrawCanvas canvas; // Declare an instance the drawing canvas (extends JPanel)
12
13 /** Constructor to set up the GUI components */
14 public CGTemplate() {
15 canvas = new DrawCanvas(); // Construct the drawing canvas
16 [Link](new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
17 [Link](canvas);
18 // Set the Drawing JPanel as the content‐pane
19 // OR
20 // Get the JFrame's content‐pane and add onto the content‐pane as follows:
21 // Container cp = getContentPane();
22 // [Link](canvas);
23
24 [Link](EXIT_ON_CLOSE); // Handle the CLOSE button
25 [Link](); // Either pack() the components; or setSize()
26 [Link]("......"); // this JFrame sets the title
27 [Link](true); // this JFrame show
28 }
29
30 /**
31 * DrawCanvas (inner class) is a JPanel used for custom drawing
32 */
33 private class DrawCanvas extends JPanel {
34 // Override paintComponent to perform your own painting
35 @Override
36 public void paintComponent(Graphics g) {
37 [Link](g); // paint parent's background
38 setBackground([Link]); // set background color for this JPanel
39
40 // Your custom painting codes. For example,
41 // Drawing primitive shapes
42 [Link]([Link]); // set the drawing color
43 [Link](30, 40, 100, 200);
44 [Link](150, 180, 10, 10);
45 [Link](200, 210, 20, 30);
46 [Link]([Link]); // change the drawing color
47 [Link](300, 310, 30, 50);
48 [Link](400, 350, 60, 50);
49 // Printing texts
50 [Link]([Link]);
51 [Link](new Font("Courier New", [Link], 12));
52 [Link]("Testing custom drawing ...", 10, 20);
53 }
54 }
5 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
55
56 /** Entry main method */
57 public static void main(String[] args) {
58 // Run the GUI codes on the Event‐Dispatching thread for thread safety
59 [Link](new Runnable() {
60 @Override
61 public void run() {
62 new CGTemplate(); // Let the constructor do the job
63 }
64 });
65 }
66 }
6 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
3.1 [Link]
The class [Link]
provides 13 standard colors as
named-constants. They are:
[Link], GREEN, BLUE,
MAGENTA, CYAN, YELLOW,
BLACK, WHITE, GRAY,
DARK_GRAY, LIGHT_GRAY,
ORANGE, and PINK. (In JDK 1.1,
these constant names are in
lowercase, e.g., red. This
violates the Java naming
convention for constants. In JDK 1.2, the uppercase names are added. The lowercase names were not
removed for backward compatibility.)
You can use the toString() to print the RGB values of these color (e.g.,
[Link]([Link])):
7 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
You can also use the RGB values or RGBA value (A for alpha to specify transparency/opaque) to construct
your own color via constructors:
For example:
To retrieve the individual components, you can use getRed(), getGreen(), getBlue(), getAlpha(),
etc.
To set the background and foreground (text) color of a component/container, you can invoke:
To set the color of the Graphics context g (for drawing lines, shapes, and texts), use
[Link](color):
[Link]([Link]);
[Link](10, 20, 30, 40); // in [Link]
Color myColor = new Color(123, 111, 222);
[Link](myColor);
[Link](10, 10, 40, 50); // in myColor
(Advanced) JColorChooser
This
example
uses the
8 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
1 import [Link].*;
2 import [Link].*;
3 import [Link].*;
4
5 /** Test ColorChooser to set the background */
6 @SuppressWarnings("serial")
7 public class JColorChooserDemo extends JFrame {
8
9 JPanel panel;
10 Color bgColor = Color.LIGHT_GRAY; // panel's background color
11
12 /** Constructor to setup the UI components */
13 public JColorChooserDemo() {
14 panel = new JPanel(new BorderLayout());
15
16 JButton btnColor = new JButton("Change Color");
17 [Link](btnColor, [Link]);
18 [Link](new ActionListener() {
19 @Override
20 public void actionPerformed(ActionEvent e) {
21 Color color = [Link]([Link],
22 "Choose a color", bgColor);
23 if (color != null) { // new color selected
24 bgColor = color;
25 }
26 [Link](bgColor); // change panel's background color
27 }
28 });
29
30 setContentPane(panel);
31
32 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
33 setTitle("JColorChooser Demo");
34 setSize(300, 200);
35 setLocationRelativeTo(null); // center the application window
36 setVisible(true); // show it
37 }
38
39 /** The entry main() method */
40 public static void main(String[] args) {
41 // Run GUI codes in the Event‐Dispatching thread for thread safety
42 [Link](new Runnable() {
43 @Override
9 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
3.2 [Link]
The class [Link] represents a specific font face, which can be used for rendering texts. You can
use the following constructor to construct a Font instance:
You can use the setFont() method to set the current font for the Graphics context g for rendering
texts. For example,
[Link][family=Arial,name=Arial,style=plain,size=1]
[Link][family=Arial,name=Arial Bold,style=plain,size=1]
[Link][family=Arial,name=Arial Bold Italic,style=plain,size=1]
[Link][family=Arial,name=Arial Italic,style=plain,size=1]
10 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
Physical font names are actual font libraries such as "Arial", "Times New Roman" in the system.
Font's deriveFont()
You can use Font's deriveFont() to derive a new Font instance from this Font with varying size, style
and others.
For example,
3.3 [Link]
The [Link] class can be used to measure the exact width and height of the string for a
particular font face, so that you can position the string as you desire (such as at the center of the screen).
// In [Link]
public abstract FontMetrics getFontMetrics(Font f)
// Get the FontMetrics of the specified font
public abstract FontMetrics getFontMetrics()
11 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
// in [Link]
public int getHeight()
public int getLeading()
public int getAscent()
public int getDescent()
The most commonly-used function for FontMetrics is to measure the width of a given String displayed
in a certain font.
12 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
arrow" and "Right-arrow" keys, and responses by moving the line left or right.
1 import [Link].*;
2 import [Link].*;
3 import [Link].*;
4 /**
5 * Custom Graphics Example: Using key/button to move a line left or right.
6 */
7 @SuppressWarnings("serial")
8 public class CGMoveALine extends JFrame {
9 // Name‐constants for the various dimensions
10 public static final int CANVAS_WIDTH = 400;
11 public static final int CANVAS_HEIGHT = 140;
12 public static final Color LINE_COLOR = [Link];
13 public static final Color CANVAS_BACKGROUND = [Link];
14
15 // The line from (x1, y1) to (x2, y2), initially position at the center
16 private int x1 = CANVAS_WIDTH / 2;
17 private int y1 = CANVAS_HEIGHT / 8;
18 private int x2 = x1;
19 private int y2 = CANVAS_HEIGHT / 8 * 7;
20
21 private DrawCanvas canvas; // the custom drawing canvas (extends JPanel)
22
23 /** Constructor to set up the GUI */
24 public CGMoveALine() {
25 // Set up a panel for the buttons
26 JPanel btnPanel = new JPanel(new FlowLayout());
27 JButton btnLeft = new JButton("Move Left ");
28 [Link](btnLeft);
29 [Link](new ActionListener() {
30 public void actionPerformed(ActionEvent e) {
31 x1 ‐= 10;
32 x2 ‐= 10;
33 [Link]();
34 requestFocus(); // change the focus to JFrame to receive KeyEvent
35 }
36 });
37 JButton btnRight = new JButton("Move Right");
38 [Link](btnRight);
39 [Link](new ActionListener() {
40 public void actionPerformed(ActionEvent e) {
41 x1 += 10;
42 x2 += 10;
43 [Link]();
44 requestFocus(); // change the focus to JFrame to receive KeyEvent
45 }
46 });
47
48 // Set up a custom drawing JPanel
49 canvas = new DrawCanvas();
50 [Link](new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
51
52 // Add both panels to this JFrame
53 Container cp = getContentPane();
13 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
54 [Link](new BorderLayout());
55 [Link](canvas, [Link]);
56 [Link](btnPanel, [Link]);
57
58 // "this" JFrame fires KeyEvent
59 addKeyListener(new KeyAdapter() {
60 @Override
61 public void keyPressed(KeyEvent evt) {
62 switch([Link]()) {
63 case KeyEvent.VK_LEFT:
64 x1 ‐= 10;
65 x2 ‐= 10;
66 repaint();
67 break;
68 case KeyEvent.VK_RIGHT:
69 x1 += 10;
70 x2 += 10;
71 repaint();
72 break;
73 }
74 }
75 });
76
77 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Handle the CLOSE button
78 setTitle("Move a Line");
79 pack(); // pack all the components in the JFrame
80 setVisible(true); // show it
81 requestFocus(); // set the focus to JFrame to receive KeyEvent
82 }
83
84 /**
85 * DrawCanvas (inner class) is a JPanel used for custom drawing
86 */
87 class DrawCanvas extends JPanel {
88 @Override
89 public void paintComponent(Graphics g) {
90 [Link](g);
91 setBackground(CANVAS_BACKGROUND);
92 [Link](LINE_COLOR);
93 [Link](x1, y1, x2, y2); // draw the line
94 }
95 }
96
97 /** The entry main() method */
98 public static void main(String[] args) {
99 // Run GUI codes on the Event‐Dispatcher Thread for thread safety
100 [Link](new Runnable() {
101 @Override
102 public void run() {
103 new CGMoveALine(); // Let the constructor do the job
104 }
105 });
106 }
107 }
14 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
The paintComponent() method is overridden to provide the custom drawing codes. We use the
drawLine() method to draw a line from (x1,y1) to (x2, y2).
The paintComponent() method cannot be called directly from your code, because it requires a
Graphics object as argument.
paintComponent() is a so-called "call-back" method. The Windowing subsystem invokes this method
and provides a pre-configured Graphics object to represent its state (e.g., current color, font, clip area
and etc). There are two kinds of painting: system-triggered painting and application-triggered painting.
In a system-trigger painting, the system request a component to render its content when the
component is first made visible on the screen, or the component is resized, or the component is
damaged that needs to be repaint. In an application-triggered painting, the application invokes a
repaint() request. Under both cases, the Windowing subsystem will call-back the
paintComponent() to render the contents of the component with a proper Graphics object as
argument.
In this example, the application requests for a repaint() in the KeyEvent and MouseEvent
handlers, which triggers the paintComponent() with an appropriate Graphics object as the
argument.
To be precise, when you invoke the repaint() method to repaint a JComponent, the Windowing
subsystem calls-back paint() method. The paint() method then calls-back three methods:
paintComponent(), paintBorder() and paintChilden().
In the overridden paintComponent() method, we call [Link]() to paint the
background of the JComponent. If this call is omitted, you must either paint the background yourself
(via a fillRect() call) or use setOpaque(false) to make the JComponent transparent. This will
inform Swing system to paint those JComponents behind the transparent component.
We choose the JFrame as the source of the KeyEvent. JFrame shall be "in focus" when the key is
pressed. The requestFocus() method (of "this" JFrame) is invoked to request for the keyboard
focus.
Try
15 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
[Link]
This class models a sprite, with its own properties, and it can paint itself via the paint() method provided
given a Graphics context. A rectangle is used here.
1 import [Link].*;
2 /**
3 * The class Sprite models a moving game object, with its own operations
4 * and can paint itself.
5 */
6 public class Sprite {
7 // Variables (package access)
8 int x, y, width, height; // rectangle (for illustration)
9 Color color = [Link]; // color of the object
10
11 /** Constructor to setup the GUI */
12 public Sprite(int x, int y, int width, int height, Color color) {
13 this.x = x;
14 this.y = y;
15 [Link] = width;
16 [Link] = height;
17 [Link] = color;
18 }
19
20 /** Paint itself (given the Graphics context) */
21 public void paint(Graphics g) {
22 [Link](color);
23 [Link](x, y, width, height); // fill a rectangle
16 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
24 }
25 }
[Link]
Instead of repainting the entire display, we only repaint the affected areas (clips), for efficiency, via the
repaint(x, y, width, height) method. In moveLeft() and moveRight(), we save the states, move
the object, repaint the saved clip-area with the background color, and repaint the new clip-area occupied
by the sprite. Repainting is done by asking the sprite to paint itself at the new location, and erase from the
old location.
1 import [Link].*;
2 import [Link].*;
3 import [Link].*;
4 /**
5 * Custom Graphics Example: Using key/button to move a object left or right.
6 * The moving object (sprite) is defined in its own class, with its own
7 * operations and can paint itself.
8 */
9 public class CGMoveASprite extends JFrame {
10 // Name‐constants for the various dimensions
11 public static final int CANVAS_WIDTH = 400;
12 public static final int CANVAS_HEIGHT = 140;
13 public static final Color CANVAS_BG_COLOR = [Link];
14
15 private DrawCanvas canvas; // the custom drawing canvas (extends JPanel)
16 private Sprite sprite; // the moving object
17
18 /** Constructor to set up the GUI */
19 public CGMoveASprite() {
20 // Construct a sprite given x, y, width, height, color
21 sprite = new Sprite(CANVAS_WIDTH / 2 ‐ 5, CANVAS_HEIGHT / 2 ‐ 40,
22 10, 80, [Link]);
23
24 // Set up a panel for the buttons
25 JPanel btnPanel = new JPanel(new FlowLayout());
26 JButton btnLeft = new JButton("Move Left ");
27 [Link](btnLeft);
28 [Link](new ActionListener() {
29 @Override
30 public void actionPerformed(ActionEvent e) {
31 moveLeft();
32 requestFocus(); // change the focus to JFrame to receive KeyEvent
33 }
34 });
35 JButton btnRight = new JButton("Move Right");
36 [Link](btnRight);
37 [Link](new ActionListener() {
38 @Override
39 public void actionPerformed(ActionEvent e) {
40 moveRight();
41 requestFocus(); // change the focus to JFrame to receive KeyEvent
42 }
43 });
17 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
44
45 // Set up the custom drawing canvas (JPanel)
46 canvas = new DrawCanvas();
47 [Link](new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
48
49 // Add both panels to this JFrame
50 Container cp = getContentPane();
51 [Link](new BorderLayout());
52 [Link](canvas, [Link]);
53 [Link](btnPanel, [Link]);
54
55 // "this" JFrame fires KeyEvent
56 addKeyListener(new KeyAdapter() {
57 @Override
58 public void keyPressed(KeyEvent evt) {
59 switch([Link]()) {
60 case KeyEvent.VK_LEFT: moveLeft(); break;
61 case KeyEvent.VK_RIGHT: moveRight(); break;
62 }
63 }
64 });
65
66 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
67 setTitle("Move a Sprite");
68 pack(); // pack all the components in the JFrame
69 setVisible(true); // show it
70 requestFocus(); // "this" JFrame requests focus to receive KeyEvent
71 }
72
73 /** Helper method to move the sprite left */
74 private void moveLeft() {
75 // Save the current dimensions for repaint to erase the sprite
76 int savedX = sprite.x;
77 // update sprite
78 sprite.x ‐= 10;
79 // Repaint only the affected areas, not the entire JFrame, for efficiency
80 [Link](savedX, sprite.y, [Link], [Link]); // Clear old area to back
81 [Link](sprite.x, sprite.y, [Link], [Link]); // Paint new location
82 }
83
84 /** Helper method to move the sprite right */
85 private void moveRight() {
86 // Save the current dimensions for repaint to erase the sprite
87 int savedX = sprite.x;
88 // update sprite
89 sprite.x += 10;
90 // Repaint only the affected areas, not the entire JFrame, for efficiency
91 [Link](savedX, sprite.y, [Link], [Link]); // Clear old area to back
92 [Link](sprite.x, sprite.y, [Link], [Link]); // Paint at new locatio
93 }
94
95 /** DrawCanvas (inner class) is a JPanel used for custom drawing */
96 class DrawCanvas extends JPanel {
97 @Override
98 public void paintComponent(Graphics g) {
18 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
99 [Link](g);
100 setBackground(CANVAS_BG_COLOR);
101 [Link](g); // the sprite paints itself
102 }
103 }
104
105 /** The entry main() method */
106 public static void main(String[] args) {
107 // Run GUI construction on the Event‐Dispatching Thread for thread safety
108 [Link](new Runnable() {
109 @Override
110 public void run() {
111 new CGMoveASprite(); // Let the constructor do the job
112 }
113 });
114 }
115 }
6. Example 3: Paint
[Link]
1 import [Link];
2 import [Link];
3 import [Link].*;
4 import [Link].*;
5 import [Link].*;
6
7 /**
8 * Custom Graphics Example: Paint
9 */
10 public class MyPaint extends JFrame {
11 // Name‐constants for the various dimensions
12 public static final int CANVAS_WIDTH = 500;
13 public static final int CANVAS_HEIGHT = 300;
14 public static final Color LINE_COLOR = [Link];
15
16 // Lines, consists of a List of PolyLine instances
17 private List<PolyLine> lines = new ArrayList<PolyLine>();
18 private PolyLine currentLine; // the current line (for capturing)
19
20 /** Constructor to set up the GUI */
21 public MyPaint() {
22 DrawCanvas canvas = new DrawCanvas();
23 [Link](new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
24 [Link](new MouseAdapter() {
19 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
25 @Override
26 public void mousePressed(MouseEvent e) {
27 // Begin a new line
28 currentLine = new PolyLine();
29 [Link](currentLine);
30 [Link]([Link](), [Link]());
31 }
32 });
33 [Link](new MouseMotionAdapter() {
34 @Override
35 public void mouseDragged(MouseEvent e) {
36 [Link]([Link](), [Link]());
37 repaint(); // invoke paintComponent()
38 }
39 });
40
41 setContentPane(canvas);
42 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
43 setTitle("Paint");
44 pack();
45 setVisible(true);
46 }
47
48 /** DrawCanvas (inner class) is a JPanel used for custom drawing */
49 private class DrawCanvas extends JPanel {
50 @Override
51 protected void paintComponent(Graphics g) { // called back via repaint()
52 [Link](g);
53 [Link](LINE_COLOR);
54 for (PolyLine line: lines) {
55 [Link](g);
56 }
57 }
58 }
59
60 /** The entry main method */
61 public static void main(String[] args) {
62 [Link](new Runnable() {
63 // Run the GUI codes on the Event‐Dispatching thread for thread safety
64 @Override
65 public void run() {
66 new MyPaint(); // Let the constructor do the job
67 }
68 });
69 }
70 }
[Link]
1 import [Link];
2 import [Link].*;
3 /*
4 * The PolyLine class model a line consisting of many points
5 */
6 public class PolyLine {
20 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
7. Drawing Images
7.1 [Link]
The [Link] class represents an icon, which is a fixed-size picture, typically small-size
and used to decorate components. To create an ImageIcon:
21 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
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) on the display.
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 this.
The drawImage() method requires an Image instance, which can be obtained via ImageIcon's
getImage() method; or via static method [Link]() (read "Reading Images into your
program"). For example,
// Prepare an ImageIcon
ImageIcon icon = null;
String imgFilename = "images/[Link]";
[Link] imgURL = getClass().getClassLoader().getResource(imgFilename);
if (imgURL != null) {
icon = new ImageIcon(imgURL);
} else {
[Link]("Couldn't find file: " + imgFilename);
}
22 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
Example
Images:
1 import [Link].*;
2 import [Link];
3 import [Link].*;
4 import [Link];
5
6 /** Test drawImage() thru ImageIcon */
7 @SuppressWarnings("serial")
8 public class CGDrawImageDemo extends JFrame {
9 // Define named‐constants for the various dimensions
10 public static final int ROWS = 3;
11 public static final int COLS = 3;
12 public static final int IMAGE_SIZE = 50;
13 public static final int PADDING = 20; // padding from the border
14 public static final int CELL_SIZE = IMAGE_SIZE + 2 * PADDING;
15 public static final int CANVAS_SIZE = CELL_SIZE * ROWS;
16
17 private DrawCanvas canvas; // The drawing canvas
18 private Random random = new Random(); // for picking images in random
19
20 // Images
21 private String imgCrossFilename = "images/[Link]";
22 private String imgNoughtFilename = "images/[Link]";
23 private Image imgCross; // drawImage() uses an Image object
24 private Image imgNought;
25
26 /** Constructor to set up the GUI components */
27 public CGDrawImageDemo() {
28 // Prepare the ImageIcon and Image objects for drawImage()
29 ImageIcon iconCross = null;
30 ImageIcon iconNought = null;
23 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
24 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
This example places absolute numbers in the draw methods, which is hard to maintain and reuse. You
should define name-constants such as CELL_WIDTH, BORDER_WIDTH, etc, and compute the numbers
based on these constants.
8. Animation
You can start and stop the Timer via the Timer's start() and stop() methods. For example,
You can use method setRepeats(false) to set the Timer to fire only once, after the delay. You can set
the initial delay via setInitialDelay() and regular delay via setDelay().
A Timer can fire the ActionEvent to more than one ActionListeners. You can register more
ActionListeners via the addActionListener() method.
The actionPerformed() runs on the event-dispatching thread, just like all the event handlers. You can
be relieved of the multi-threading issues.
25 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
JDK 1.3 introduced another timer class called [Link], which is more general, but
[Link] is sufficient (and easier) to run animation in Swing application.
26 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
50 ySpeed = ‐ySpeed;
51 }
52 }
53
54 /** DrawCanvas (inner class) is a JPanel used for custom drawing */
55 private class DrawCanvas extends JPanel {
56 @Override
57 public void paintComponent(Graphics g) {
58 [Link](g); // paint parent's background
59 setBackground([Link]);
60 [Link]([Link]);
61 [Link](x, y, size, size); // draw a circle
62 }
63 }
64
65 /** The entry main method */
66 public static void main(String[] args) {
67 // Run GUI codes in Event‐Dispatching thread for thread safety
68 [Link](new Runnable() {
69 @Override
70 public void run() {
71 new CGBouncingBallSwingTimer(); // Let the constructor do the job
72 }
73 });
74 }
75 }
[Link] does not provide very accurate timing due to the overhead of event-handling. It
probaly cannot be used for real-time application such as displaying a clock.
To ensure the new thread does not starve the other threads, in particular the event-dispatching thread, the
thread shall yield control via the sleep(mills) method, which also provides the necessary delay.
1 import [Link].*;
27 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
2 import [Link].*;
3
4 /** Bouncing Ball (Animation) via custom thread */
5 public class CGBouncingBall extends JFrame {
6 // Define named‐constants
7 private static final int CANVAS_WIDTH = 640;
8 private static final int CANVAS_HEIGHT = 480;
9 private static final int UPDATE_INTERVAL = 50; // milliseconds
10
11 private DrawCanvas canvas; // the drawing canvas (extends JPanel)
12
13 // Attributes of moving object
14 private int x = 100; // top‐left (x, y)
15 private int y = 100;
16 private int size = 250; // width and height
17 private int xSpeed = 3; // moving speed in x and y directions
18 private int ySpeed = 5; // displacement per step in x and y
19
20 /** Constructor to setup the GUI components */
21 public CGBouncingBall() {
22 canvas = new DrawCanvas();
23 [Link](new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
24 [Link](canvas);
25 [Link](EXIT_ON_CLOSE);
26 [Link]();
27 [Link]("Bouncing Ball");
28 [Link](true);
29
30 // Create a new thread to run update at regular interval
31 Thread updateThread = new Thread() {
32 @Override
33 public void run() {
34 while (true) {
35 update(); // update the (x, y) position
36 repaint(); // Refresh the JFrame. Called back paintComponent()
37 try {
38 // Delay and give other thread a chance to run
39 [Link](UPDATE_INTERVAL); // milliseconds
40 } catch (InterruptedException ignore) {}
41 }
42 }
43 };
44 [Link](); // called back run()
45 }
46
47 /** Update the (x, y) position of the moving object */
48 public void update() {
49 x += xSpeed;
50 y += ySpeed;
51 if (x > CANVAS_WIDTH ‐ size || x < 0) {
52 xSpeed = ‐xSpeed;
53 }
54 if (y > CANVAS_HEIGHT ‐ size || y < 0) {
55 ySpeed = ‐ySpeed;
56 }
28 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
57 }
58
59 /** DrawCanvas (inner class) is a JPanel used for custom drawing */
60 class DrawCanvas extends JPanel {
61 @Override
62 public void paintComponent(Graphics g) {
63 [Link](g); // paint parent's background
64 setBackground([Link]);
65 [Link]([Link]);
66 [Link](x, y, size, size); // draw a circle
67 }
68 }
69
70 /** The entry main method */
71 public static void main(String[] args) {
72 // Run GUI codes in Event‐Dispatching thread for thread safety
73 [Link](new Runnable() {
74 @Override
75 public void run() {
76 new CGBouncingBall(); // Let the constructor do the job
77 }
78 });
79 }
80 }
To update the display regularly, we explicitly invoke the repaint() method of the JFrame, which will
callback the paintComponent(g) of all the components contained in this JFrame.
The display refreshing code is run in its own thread, so as to avoid the infamous unresponsive user
interface problem. It is programmed as an anonymous inner class, extends class Thread, by overriding
the run() method to provide the programmed operations (i.e., repaint()). The start() method is
use to start the thread, which will callback the run().
Inside the overridden run(), the repaint() is programmed inside an infinite loop, followed by a
[Link](milliseconds) method, which suspends the thread for the given milliseconds. This
operation provides the necessary delay and also yield control to other thread to perform their intended
operations.
29 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
Painting Mechanism
Painting is carried out via a "call-back" mechanism. A program shall put its painting codes in a overridden
method (paint() for AWT components or paintComponent() for Swing component), and the
windowing subsystem will call back this method when it's time to paint.
Instead of issuing repaint() to paint the entire component, for efficiency, you can selectively repaint a
rectangular clip area. You can also specify a maximum time limit for painting to take place.
30 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
To improve performance of opaque components, Swing adds a property called opaque to all
JComponents. If opaque is set to true, the component agrees to paint all of the pixels contained within
its rectangular bounds. In order words, the windowing subsystem does not have to do anything within
these bounds such as painting its ancestors. It opaque is set to false, the component makes no
guarantees about painting all the bits within its rectangular bounds, and the windowing subsystem has
more work to do.
Swing further factor the paint() method into three methods, which are invoked in the following order:
Most of the standard Swing components (in particular, JPanel) have their look and feel implemented by
separate look-and-feel objects (called "UI delegates") for Swing's Pluggable look and feel feature. This
means that most or all of the painting for the standard components is delegated to the UI delegate and
this occurs in the following way:
1. paint() invokes paintComponent().
2. If the ui property is non-null, paintComponent() invokes [Link]().
3. If the component's opaque property is true, [Link]() fills the component's background with
the background color and invokes [Link]().
4. [Link]() renders the content of the component.
This means that subclasses of Swing components which have a UI delegate (such as JPanel), should
invoke [Link]() within their overridden paintComponent(), so that [Link]()
fills the background (of the superclass such as JPanel) provided opaque is true.
Try removing the [Link]() from a Swing program that does animation (e.g., bouncing
ball). The background will not be painted, and the previous screen may not be cleared. You can also paint
the background yourself by filling a Rectangle with background color.
31 of 32 10/18/2013 9:09 AM
Custom Graphics Programming - Java Programming Tutorial [Link]
@Override
protected void paintComponent(Graphics g) {
[Link](backgroundColor);
[Link](0, 0, getWidth() ‐ 1, getHeight() ‐ 1);
}
Furthermore, if you set the opaque to false (via setOpaque(false)) for the subclass of JPanel, the
[Link](g) does not fill the background.
Feedback, comments, corrections, and errata can be sent to Chua Hock-Chuan (ehchua@[Link])
| HOME
32 of 32 10/18/2013 9:09 AM
When selecting between javax.swing.Timer and threads for implementing animation in Java applications, developers must consider the trade-offs between simplicity and precision. javax.swing.Timer is simpler to use and integrates well with the event-dispatching thread, making it suitable for straightforward animations where the timing precision is not critical. It encapsulates multi-threading complexities and easily updates the graphic components at intervals. However, it suffers from less precision due to event-handling overhead, unsuitable for high-resolution animations. On the other hand, using threads allows finer control over timing and parallel execution, enabling smoother animations for complex and high-performance requirements. This approach, however, introduces additional complexity related to thread management, synchronization, and potential race conditions, making it harder to maintain and perform correctly under all conditions .
The significance of using javax.swing.Timer in Swing applications lies in its ability to perform tasks at regular intervals on the event-dispatching thread, allowing animations to be controlled with periodic updates without delving into complex multi-threading. It simplifies animation timing, making it easier for developers to implement animated movements, like a bouncing ball, by encapsulating timing logic within a GUI framework. However, its limitations include less precise timing due to the overhead of event-handling, which may result in inaccuracies over time or frame skipping in animations. Such limitations make javax.swing.Timer unsuitable for real-time applications requiring high timing precision, like clock displays .
The ImageIcon class in the javax.swing package facilitates image integration by acting as a bridge between image files and GUI components. It allows developers to easily load and display small-sized images, often used as icons to decorate components. ImageIcons are fixed-size and straightforward to use, making them ideal for adding static images to buttons, labels, and other components that support icons. By handling image loading and providing the getImage method, ImageIcon enables fundamental image operations, allowing further manipulation and display adjustments if needed .
A custom JPanel class enhances custom graphics drawing in Java applications by providing a dedicated area for managing and rendering graphics operations independently of other components. By extending JPanel, developers can override the paintComponent method to perform specific drawing tasks such as rendering shapes, images, and animations without affecting the rest of the user interface. This separation allows for efficient and reusable code design, where the JPanel class handles all logic associated with rendering graphics, and changes to the drawing logic do not interfere with the application's main controls or other UI components .
Custom Graphics classes provide a foundational role in Java game development by allowing developers to create and manipulate visual elements not readily available through standard GUI components. These classes facilitate direct control over rendering operations, enabling the implementation of complex graphics such as animations, game worlds, and interactive objects essential for gameplay. To effectively use custom Graphics in gaming, developers should aim to reuse standard graphics components wherever possible, resorting to custom graphics when mandatory. Additionally, optimizing rendering performance through targeted use of the repaint method and efficient state management within graphics contexts is recommended to handle demanding graphical computations and maintain responsive interactions .
The PolyLine class in Java custom graphics programming is used to model and draw lines that consist of multiple connected points. It maintains lists of x and y coordinates to represent the connected sequence. Using the addPoint method, the PolyLine can dynamically add new points to these sequences. The draw method leverages the Graphics class's drawing capabilities to iterate through the points and draw lines between consecutive points, effectively rendering a polyline on the graphics context. This encapsulated approach simplifies the management and rendering of connected graphical elements .
The custom painting template in a Java application is structured by extending a component, commonly JPanel, and overriding its paintComponent method to include specific drawing code. The template offers a framework for rendering custom graphics like shapes, text, and images by using the Graphics object provided in the paintComponent method to perform various drawing operations. It plays a crucial role in separating the drawing logic from the main program logic, efficiently organizing code related to graphical updates while ensuring that such updates are appropriately called, often in response to events or the repaint method .
In the Graphics context of a Java application, "clip" areas define the portion of the graphics where rendering operations are permitted. When a clip area is set, any drawing outside the defined rectangular clip bounds is ignored, which can be used to limit the rendering scope to specific areas and optimize performance by preventing unnecessary drawing operations. Methods like setClip and clipRect allow developers to specify these clipping areas. Using clip efficiently can help manage complex scenes where only partial repainting is needed, reducing the rendering load on the system .
The java.awt.Graphics class handles transparency in images using the drawImage method, which has an option to specify a background color for transparent pixels. This background color is used to fill the areas where the source image has transparency. A potential issue developers should be aware of is that specifying a background color can affect the visual appearance of the image if the color does not match the intended transparency effect. Developers need to carefully choose the bgcolor parameter to align with the design requirements .
The use of the repaint method in Java applications provides several advantages for managing GUI updates. It allows deferred and optimized painting of component changes by signaling the system to schedule a call to the component's paintComponent method. This approach ensures that multiple updates are handled efficiently in a single operation, reducing the computational cost compared to immediate and repeated painting. Additionally, using repaint to specify only the affected area of a component minimizes the rendering workload, enhancing the application's performance and responsiveness during user interactions and animations .