public final class DrawingPanel extends Object implements ImageObserver
Authors: Marty Stepp (Stanford University) and Stuart Reges (University of Washington).
Version: 4.04, 2016/08/17 (to accompany BJP 4th edition).
You can always download the latest DrawingPanel
from
http://www.buildingjavaprograms.com/drawingpanel/DrawingPanel.java .
For more information and related materials, please visit www.buildingjavaprograms.com .
COMPATIBILITY NOTE: This version of DrawingPanel requires Java 8 or higher. To make this file work on Java 7 and lower, you must make two small modifications to its source code. Search for the two occurrences of the annotation @FunctionalInterface and comment them out or remove those lines. Then the file should compile and run properly on older versions of Java.
The DrawingPanel
class provides a simple interface for drawing persistent
images using a Graphics
object. An internal BufferedImage
object is used
to keep track of what has been drawn. A client of the class simply
constructs a DrawingPanel
of a particular size and then draws on it with
the Graphics
object, setting the background color if they so choose.
The intention is that this custom library will mostly "stay out of the way"
so that the client mostly interacts with a standard Java java.awt.Graphics
object, and therefore most of the experience gained while using this library
will transfer to Java graphics programming in other contexts.
DrawingPanel
is not intended to be a full rich graphical library for things
like object-oriented drawing of shapes, animations, creating games, etc.
Here is a canonical example of creating a DrawingPanel
of a given size and
using it to draw a few shapes.
// basic usage example DrawingPanel panel = new DrawingPanel(600, 400); Graphics g = panel.getGraphics(); g.setColor(Color.RED); g.fillRect(17, 45, 139, 241); g.drawOval(234, 77, 100, 100); ...
To ensure that the image is always displayed, a timer calls repaint at regular intervals.
This version of DrawingPanel
allows you to loop over the pixels of an image.
You can process each pixel as a Color
object (easier OO interface, but takes
more CPU and memory to run) or as a 32-bit RGB integer (clunkier to use, but
much more efficient in runtime and memory usage).
Look at the methods get/setPixel(s) to get a better idea.
// example of horizontally flipping an image public static void flipHorizontal(DrawingPanel panel) { int width = panel.getWidth(); int height = panel.getHeight(); int[][] pixels = panel.getPixelsRGB(); for (int row = 0; row < height; row++) { for (int col = 0; col < width / 2; col++) { // swap this pixel with the one opposite it int col2 = width - 1 - col; int temp = pixels[row][col]; pixels[row][col] = pixels[row][col2]; pixels[row][col2] = temp; } } panel.setPixels(pixels); }
With Java 8, you can now attach event handlers to listen to keyboard and mouse
events that occur in a DrawingPanel
using a lambda function. For example:
// example of attaching a mouse click handler using Java 8 panel.onClick( (x, y) -> System.out.println(x + " " + y) );
This version now includes an inner class named DebuggingGraphics
that keeps track of how many times various drawing methods are called.
It includes a showCounts
method for the DrawingPanel
itself
that allows a client to examine this. The panel will record basic drawing
methods performed by a version of the Graphics
class obtained by
calling getDebuggingGraphics
:
// example of debugging counts of graphics method calls Graphics g = panel.getDebuggingGraphics();
Novices will be encouraged to simply print it at the end of main
, as in:
System.out.println(panel.getCounts());
2016/03/07 - Code cleanup and improvements to JavaDoc comments for BJP4 release.
2015/09/04 - Now includes methods for get/setting individual pixels and all pixels on the drawing panel. This helps facilitate 2D array-based pixel-processing exercises and problems for Building Java Programs, 4th edition. - Code cleanup and reorganization. Now better alphabetization/formatting of members and encapsulation. Commenting also augmented throughout code.
2015/04/09 - Now includes a DebuggingGraphics inner class that keeps track of how many times various drawing methods are called. All additions are commented (search for "DebuggingGraphics")
2011/10/25 - save zoomed images (2011/10/25)
2011/10/21 - window no longer moves when zoom changes - grid lines
Modifier and Type | Class and Description |
---|---|
static interface |
DrawingPanel.DPKeyEventHandler
This functional interface is provided to allow Java 8 clients to write
lambda functions to handle key events that occur in a DrawingPanel.
|
static interface |
DrawingPanel.DPMouseEventHandler
This functional interface is provided to allow Java 8 clients to write
lambda functions to handle mouse events that occur in a DrawingPanel.
|
Modifier and Type | Field and Description |
---|---|
static String |
ANIMATED_PROPERTY
An internal constant for setting system properties; clients should not use this.
|
static String |
ANIMATION_FILE_NAME
An internal constant for setting system properties; clients should not use this.
|
static String |
ANTIALIAS_PROPERTY
An internal constant for setting system properties; clients should not use this.
|
static String |
AUTO_ENABLE_ANIMATION_ON_SLEEP_PROPERTY
An internal constant for setting system properties; clients should not use this.
|
static int |
DEFAULT_HEIGHT
The default height of a DrawingPanel in pixels, if none is supplied at construction (400 pixels).
|
static int |
DEFAULT_WIDTH
The default width of a DrawingPanel in pixels, if none is supplied at construction (500 pixels).
|
static String |
DIFF_PROPERTY
An internal constant for setting system properties; clients should not use this.
|
static String |
HEADLESS_PROPERTY
An internal constant for setting system properties; clients should not use this.
|
static String |
MULTIPLE_PROPERTY
An internal constant for setting system properties; clients should not use this.
|
static int |
PIXEL_ALPHA
An RGB integer representing alpha at 100% opacity (0xff000000).
|
static int |
PIXEL_BLUE
An RGB integer representing 100% blue (0x000000ff).
|
static int |
PIXEL_GREEN
An RGB integer representing 100% green (0x0000ff00).
|
static int |
PIXEL_RED
An RGB integer representing 100% red (0x00ff0000).
|
static String |
SAVE_PROPERTY
An internal constant for setting system properties; clients should not use this.
|
ABORT, ALLBITS, ERROR, FRAMEBITS, HEIGHT, PROPERTIES, SOMEBITS, WIDTH
Constructor and Description |
---|
DrawingPanel()
Constructs a drawing panel with a default width and height enclosed in a window.
|
DrawingPanel(File imageFile)
Constructs a drawing panel that displays the image from the given file enclosed in a window.
|
DrawingPanel(int width,
int height)
Constructs a drawing panel of given width and height enclosed in a window.
|
DrawingPanel(String imageFileName)
Constructs a drawing panel that displays the image from the given file name enclosed in a window.
|
Modifier and Type | Method and Description |
---|---|
void |
addKeyListener(KeyListener listener)
Adds the given event listener to respond to key events on this panel.
|
void |
addMouseListener(MouseListener listener)
Adds the given event listener to respond to mouse events on this panel.
|
void |
clear()
Erases all drawn shapes/lines/colors from the panel.
|
static int |
getAlpha(int rgb)
Returns the alpha (opacity) component of the given RGB pixel from 0-255.
|
static int |
getBlue(int rgb)
Returns the blue component of the given RGB pixel from 0-255.
|
Map<String,Integer> |
getCounts()
Returns a map of counts of occurrences of calls of various drawing methods.
|
Graphics |
getDebuggingGraphics()
A variation of getGraphics that returns an object that records
a count for various drawing methods.
|
Graphics2D |
getGraphics()
Obtain the Graphics object to draw on the panel.
|
static int |
getGreen(int rgb)
Returns the green component of the given RGB pixel from 0-255.
|
int |
getHeight()
Returns the drawing panel's height in pixels.
|
Color |
getPixel(int x,
int y)
Returns the color of the pixel at the given x/y coordinate as a Color object.
|
int |
getPixelRGB(int x,
int y)
Returns the color of the pixel at the given x/y coordinate as an RGB integer.
|
Color[][] |
getPixels()
Returns the colors of all pixels in this DrawingPanel as a 2-D array
of Color objects.
|
int[][] |
getPixelsRGB()
Returns the colors of all pixels in this DrawingPanel as a 2-D array
of RGB integers.
|
static int |
getRed(int rgb)
Returns the red component of the given RGB pixel from 0-255.
|
static String |
getSaveFileName()
Returns the file name used for saving all DrawingPanel instances.
|
Dimension |
getSize()
Returns the drawing panel's pixel size (width, height) as a Dimension object.
|
int |
getWidth()
Returns the drawing panel's width in pixels.
|
int |
getX()
Returns the drawing panel's x-coordinate on the screen.
|
int |
getY()
Returns the drawing panel's y-coordinate on the screen.
|
int |
getZoom()
Returns the drawing panel's current zoom factor.
|
boolean |
imageUpdate(Image img,
int infoflags,
int x,
int y,
int width,
int height)
Internal method;
notifies the panel when images are loaded and updated.
|
static boolean |
isAntiAliasDefault()
Returns true if DrawingPanel instances should anti-alias (smooth) their graphics.
|
static boolean |
isHeadless()
Returns true if the class is in "headless" mode, meaning that it is running on
a server without a graphical user interface.
|
Image |
loadImage(File file)
Loads an image from the given file on disk and returns it
as an Image object.
|
Image |
loadImage(String filename)
Loads an image from the given file on disk and returns it
as an Image object.
|
static boolean |
mainIsActive()
Internal method; returns whether the 'main' thread is still running.
|
void |
onClick(DrawingPanel.DPMouseEventHandler e)
Adds an event handler for mouse clicks.
|
void |
onDrag(DrawingPanel.DPMouseEventHandler e)
Adds an event handler for mouse drags.
|
void |
onEnter(DrawingPanel.DPMouseEventHandler e)
Adds an event handler for mouse enters.
|
void |
onExit(DrawingPanel.DPMouseEventHandler e)
Adds an event handler for mouse exits.
|
void |
onKeyDown(DrawingPanel.DPKeyEventHandler e)
Adds an event handler for key presses.
|
void |
onKeyUp(DrawingPanel.DPKeyEventHandler e)
Adds an event handler for key releases.
|
void |
onMouseClick(DrawingPanel.DPMouseEventHandler e)
Adds an event handler for mouse clicks.
|
void |
onMouseDown(DrawingPanel.DPMouseEventHandler e)
Adds an event handler for mouse button down events.
|
void |
onMouseDrag(DrawingPanel.DPMouseEventHandler e)
Adds an event handler for mouse drags.
|
void |
onMouseEnter(DrawingPanel.DPMouseEventHandler e)
Adds an event handler for mouse enters.
|
void |
onMouseExit(DrawingPanel.DPMouseEventHandler e)
Adds an event handler for mouse exits.
|
void |
onMouseMove(DrawingPanel.DPMouseEventHandler e)
Adds an event handler for mouse movement.
|
void |
onMouseUp(DrawingPanel.DPMouseEventHandler e)
Adds an event handler for mouse button up events.
|
void |
onMove(DrawingPanel.DPMouseEventHandler e)
Adds an event handler for mouse movement.
|
void |
save(File file)
Takes the current contents of the drawing panel and writes them to
the given file.
|
void |
save(String filename)
Takes the current contents of the drawing panel and writes them to
the given file.
|
static void |
saveAll()
Saves every DrawingPanel instance that is active.
|
void |
saveAnimated(File file)
Takes the current contents of the drawing panel and writes them to
the given file.
|
void |
saveAnimated(String filename)
Takes the current contents of the drawing panel and writes them to
the given file.
|
void |
setAlwaysOnTop(boolean alwaysOnTop)
Sets whether the panel will always cover other windows (default false).
|
void |
setAntiAlias(boolean antiAlias)
Sets whether the panel should use anti-aliased / smoothed graphics (default true).
|
static void |
setAntiAliasDefault(Boolean value)
Sets whether DrawingPanel instances should anti-alias (smooth) their pixels by default.
|
void |
setBackground(Color c)
Sets the background color of the drawing panel to be the given color.
|
void |
setBackground(int rgb)
Sets the background color of the drawing panel to be the color
represented by the given RGB integer.
|
void |
setGridLines(boolean gridLines)
Enables or disables the drawing of grid lines on top of the image to help
with debugging sizes and coordinates.
|
void |
setGridLines(boolean gridLines,
int pxGap)
Enables or disables the drawing of grid lines on top of the image to help
with debugging sizes and coordinates.
|
static void |
setHeadless(Boolean value)
Sets the class to run in "headless" mode, with no graphical output on screen.
|
void |
setHeight(int height)
Sets the drawing panel's height in pixels to the given value.
|
void |
setPixel(int x,
int y,
Color color)
Sets the color of the pixel at the given x/y coordinate to be the given color.
|
void |
setPixel(int x,
int y,
int rgb)
Sets the color of the pixel at the given x/y coordinate to be the color
represented by the given RGB integer.
|
void |
setPixelRGB(int x,
int y,
int rgb)
Sets the color of the pixel at the given x/y coordinate to be the color
represented by the given RGB integer.
|
void |
setPixels(Color[][] pixels)
Sets the colors of all pixels in this DrawingPanel to the colors
in the given 2-D array of Color objects.
|
void |
setPixels(int[][] pixels)
Sets the colors of all pixels in this DrawingPanel to the colors
represented by the given 2-D array of RGB integers.
|
void |
setPixelsRGB(int[][] pixels)
Sets the colors of all pixels in this DrawingPanel to the colors
represented by the given 2-D array of RGB integers.
|
static void |
setSaveFile(File file)
Sets the file to be used when saving graphical output for all DrawingPanels.
|
static void |
setSaveFileName(String filename)
Sets the filename to be used when saving graphical output for all DrawingPanels.
|
void |
setSize(int width,
int height)
Sets the drawing panel's pixel size (width, height) to the given values.
|
void |
setVisible(boolean visible)
Show or hide the drawing panel on the screen.
|
void |
setWidth(int width)
Sets the drawing panel's width in pixels to the given value.
|
void |
sleep(int millis)
Causes the program to pause for the given amount of time in milliseconds.
|
void |
toFront()
Moves the drawing panel window on top of other windows so it can be seen.
|
static int |
toRgbInteger(int r,
int g,
int b)
Returns an RGB integer made from the given red, green, and blue components
from 0-255.
|
static int |
toRgbInteger(int alpha,
int r,
int g,
int b)
Returns an RGB integer made from the given alpha, red, green, and blue components
from 0-255.
|
void |
zoom(int zoomFactor)
Zooms the drawing panel in/out to the given factor.
|
public static final int PIXEL_ALPHA
public static final int PIXEL_BLUE
public static final int PIXEL_GREEN
public static final int PIXEL_RED
public static final int DEFAULT_WIDTH
public static final int DEFAULT_HEIGHT
public static final String ANIMATED_PROPERTY
public static final String ANIMATION_FILE_NAME
public static final String ANTIALIAS_PROPERTY
public static final String AUTO_ENABLE_ANIMATION_ON_SLEEP_PROPERTY
public static final String DIFF_PROPERTY
public static final String HEADLESS_PROPERTY
public static final String MULTIPLE_PROPERTY
public static final String SAVE_PROPERTY
public DrawingPanel()
public DrawingPanel(int width, int height)
width
- panel's width in pixelsheight
- panel's height in pixelspublic DrawingPanel(File imageFile)
imageFile
- the image file to loadRuntimeException
- if the image file is not foundpublic DrawingPanel(String imageFileName)
imageFileName
- the file name/path of the image file to loadRuntimeException
- if the image file is not foundpublic static int getAlpha(int rgb)
rgb
- RGB integer with alpha in bits 0-7, red in bits 8-15, green in
bits 16-23, and blue in bits 24-31public static int getBlue(int rgb)
rgb
- RGB integer with alpha in bits 0-7, red in bits 8-15, green in
bits 16-23, and blue in bits 24-31public static int getGreen(int rgb)
rgb
- RGB integer with alpha in bits 0-7, red in bits 8-15, green in
bits 16-23, and blue in bits 24-31public static int getRed(int rgb)
rgb
- RGB integer with alpha in bits 0-7, red in bits 8-15, green in
bits 16-23, and blue in bits 24-31public static String getSaveFileName()
public static boolean isAntiAliasDefault()
public static boolean isHeadless()
public static boolean mainIsActive()
public static void saveAll() throws IOException
IOException
- if unable to save any of the files.public static void setAntiAliasDefault(Boolean value)
value
- whether to enable anti-aliasing (default true)public static void setHeadless(Boolean value)
value
- whether to enable headless mode (default false)public static void setSaveFile(File file)
file
- the file to use as default save filepublic static void setSaveFileName(String filename)
filename
- the name/path of the file to use as default save filepublic static int toRgbInteger(int r, int g, int b)
r
- red component from 0-255 (bits 8-15)g
- green component from 0-255 (bits 16-23)b
- blue component from 0-255 (bits 24-31)IllegalArgumentException
- if r, g, or b is not in 0-255 rangepublic static int toRgbInteger(int alpha, int r, int g, int b)
alpha
- alpha (transparency) component from 0-255 (bits 0-7)r
- red component from 0-255 (bits 8-15)g
- green component from 0-255 (bits 16-23)b
- blue component from 0-255 (bits 24-31)IllegalArgumentException
- if alpha, r, g, or b is not in 0-255 rangepublic void addKeyListener(KeyListener listener)
listener
- the key event listener to attachpublic void addMouseListener(MouseListener listener)
listener
- the mouse event listener to attachpublic void clear()
public Map<String,Integer> getCounts()
public Graphics getDebuggingGraphics()
public Graphics2D getGraphics()
public int getHeight()
public Color getPixel(int x, int y)
x
- x-coordinate of pixel to retrievey
- y-coordinate of pixel to retrieveIllegalArgumentException
- if (x, y) is out of rangepublic int getPixelRGB(int x, int y)
x
- x-coordinate of pixel to retrievey
- y-coordinate of pixel to retrieveIllegalArgumentException
- if (x, y) is out of rangepublic Color[][] getPixels()
public int[][] getPixelsRGB()
public Dimension getSize()
public int getWidth()
public int getX()
public int getY()
public int getZoom()
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height)
imageUpdate
in interface ImageObserver
img
- internal method; do not callinfoflags
- internal method; do not callx
- internal method; do not cally
- internal method; do not callwidth
- internal method; do not callheight
- internal method; do not callfalse
if the infoflags indicate that the
image is completely loaded; true
otherwise.ImageObserver.WIDTH
,
ImageObserver.HEIGHT
,
ImageObserver.PROPERTIES
,
ImageObserver.SOMEBITS
,
ImageObserver.FRAMEBITS
,
ImageObserver.ALLBITS
,
ImageObserver.ERROR
,
ImageObserver.ABORT
,
Image.getWidth(java.awt.image.ImageObserver)
,
Image.getHeight(java.awt.image.ImageObserver)
,
Graphics.drawImage(java.awt.Image, int, int, java.awt.image.ImageObserver)
public Image loadImage(File file)
file
- the file to loadNullPointerException
- if filename is nullRuntimeException
- if the given file is not foundpublic Image loadImage(String filename)
filename
- name/path of the file to loadNullPointerException
- if filename is nullRuntimeException
- if the given file is not foundpublic void onClick(DrawingPanel.DPMouseEventHandler e)
e
- event handler function to callNullPointerException
- if event handler is nullpublic void onDrag(DrawingPanel.DPMouseEventHandler e)
e
- event handler function to callNullPointerException
- if event handler is nullpublic void onEnter(DrawingPanel.DPMouseEventHandler e)
e
- event handler function to callNullPointerException
- if event handler is nullpublic void onExit(DrawingPanel.DPMouseEventHandler e)
e
- event handler function to callNullPointerException
- if event handler is nullpublic void onKeyDown(DrawingPanel.DPKeyEventHandler e)
e
- event handler function to callNullPointerException
- if event handler is nullpublic void onKeyUp(DrawingPanel.DPKeyEventHandler e)
e
- event handler function to callNullPointerException
- if event handler is nullpublic void onMouseClick(DrawingPanel.DPMouseEventHandler e)
e
- event handler function to callNullPointerException
- if event handler is nullpublic void onMouseDown(DrawingPanel.DPMouseEventHandler e)
e
- event handler function to callNullPointerException
- if event handler is nullpublic void onMouseDrag(DrawingPanel.DPMouseEventHandler e)
e
- event handler function to callNullPointerException
- if event handler is nullpublic void onMouseEnter(DrawingPanel.DPMouseEventHandler e)
e
- event handler function to callNullPointerException
- if event handler is nullpublic void onMouseExit(DrawingPanel.DPMouseEventHandler e)
e
- event handler function to callNullPointerException
- if event handler is nullpublic void onMouseMove(DrawingPanel.DPMouseEventHandler e)
e
- event handler function to callNullPointerException
- if event handler is nullpublic void onMouseUp(DrawingPanel.DPMouseEventHandler e)
e
- event handler function to callNullPointerException
- if event handler is nullpublic void onMove(DrawingPanel.DPMouseEventHandler e)
e
- event handler function to callNullPointerException
- if event handler is nullpublic void save(File file) throws IOException
file
- the file to saveNullPointerException
- if filename is nullIOException
- if the given file cannot be writtenpublic void save(String filename) throws IOException
filename
- name/path of the file to saveNullPointerException
- if filename is nullIOException
- if the given file cannot be writtenpublic void saveAnimated(File file) throws IOException
file
- the file to saveNullPointerException
- if filename is nullIOException
- if the given file cannot be writtenpublic void saveAnimated(String filename) throws IOException
filename
- name/path of the file to saveNullPointerException
- if filename is nullIOException
- if the given file cannot be writtenpublic void setAlwaysOnTop(boolean alwaysOnTop)
alwaysOnTop
- true if the panel should always cover other windowspublic void setAntiAlias(boolean antiAlias)
antiAlias
- true if the panel should be smoothedpublic void setBackground(Color c)
c
- color to use as backgroundNullPointerException
- if color is nullpublic void setBackground(int rgb)
rgb
- RGB integer to use as background color (full alpha assumed/applied)public void setGridLines(boolean gridLines)
gridLines
- whether to show grid lines (true) or not (false)public void setGridLines(boolean gridLines, int pxGap)
gridLines
- whether to show grid lines (true) or not (false)pxGap
- number of pixels between grid linespublic void setHeight(int height)
height
- height, in pixelsIllegalArgumentException
- if height is negative or exceeds MAX_SIZEpublic void setPixel(int x, int y, Color color)
x
- x-coordinate of pixel to sety
- y-coordinate of pixel to setcolor
- Color to set the pixel to useIllegalArgumentException
- if x or y is out of boundsNullPointerException
- if color is nullpublic void setPixel(int x, int y, int rgb)
x
- x-coordinate of pixel to sety
- y-coordinate of pixel to setrgb
- RGB integer representing the color to set the pixel to useIllegalArgumentException
- if x or y is out of boundspublic void setPixelRGB(int x, int y, int rgb)
x
- x-coordinate of pixel to sety
- y-coordinate of pixel to setrgb
- RGB integer representing the color to set the pixel to useIllegalArgumentException
- if x or y is out of boundspublic void setPixels(Color[][] pixels)
pixels
- 2D array of pixels (row-major)NullPointerException
- if pixels array is nullpublic void setPixels(int[][] pixels)
pixels
- 2D array of pixels (row-major)NullPointerException
- if pixels array is nullpublic void setPixelsRGB(int[][] pixels)
pixels
- 2D array of pixels (row-major)NullPointerException
- if pixels array is nullpublic void setSize(int width, int height)
width
- width, in pixelsheight
- height, in pixelsIllegalArgumentException
- if width/height is negative or exceeds MAX_SIZEpublic void setVisible(boolean visible)
visible
- true to show, false to hidepublic void setWidth(int width)
width
- width, in pixelsIllegalArgumentException
- if height is negative or exceeds MAX_SIZEpublic void sleep(int millis)
millis
- number of milliseconds to sleepIllegalArgumentException
- if a negative number of ms is passedpublic void toFront()
public void zoom(int zoomFactor)
zoomFactor
- the zoom factor to use (1 or greater)