In this article we will cover basic 2D drawing in Java using the Graphics class, Image class, Font class and Color class.
We won’t go in-depth into every possible way to draw in Java because that would be quite a lot, but we will cover the basics and provide further information and details so that you later on on your own can find out more about whats possible to do with drawing in Java if you are interested.
To understand the components that we use when working with the Graphics class we will start by covering these briefly below:
Introduction to the Color class in Java
Pre-programmed color values in the Color class in Java
The Color class contains pre-programmed static constants for common Color values, which you can see in below list:
Color space used and represented in the Color class in Java
The Java Color class uses sRGB color space for it’s colors which is more consistent than Adobe RGB.
sRGB is the world’s default color space and is the most accurate color representation of the two alternatives. Adobe RGB for example can cause color mismatch between screen and print. If you’re interested in this you can read more in the great article on Ken Rockwells website here.
Defining your very own colors using the Color class in Java
The Color class can also be used to define your very own color with the help of assigning the amount of Red, Green and Blue as well as Alpha-channel (for transperancy) when calling the Color class various constructors.
The two easiest constructors in my humble opinion for the Color class in Java are the two following (basing this on my history and experience from web development they seem the most familiar and easy to use and understand):
Color color = new Color(int r, int g, int b); // where int r,g,b each represent an integer value between 0-255 (256 possible color values counting the 0) Color color2 = new Color(int r, int g, int b, int a); // same as above here, integer values ranging between 0-255 to represent the 256 possible color values of the Hexadecimal number system used for RGB/sRGB color representation
For a more practical example this could look like following:
Color red = new Color(255,0,0); // Create a fully Red color Color green = new Color(0,255,0); // Create a fully Green color Color blue = new Color(0,0,255); // Create a fully Blue color Color black = new Color(0,0,0); // Create Black color Color white = new Color(255,255,255); // Create white color Color greyNuance = new Color(150,150,150); // Creates a 150/255 grey color
Hexadecimal number system used for color representation explained
It’s very common, especially for the web, to use hexadecimal number system for color representation, if you have ever dabbled with websites you’ve probably seen once or twice the #A5b632 hexadecimal color values. To give you some further insights into specifically how this system works, I will here explain how you turn the 0-255 integer values into hexadecimal values and the other way around!
Let’s start with the question – why 0-255?
Well bear with me on this because we’re about to venture deep into the rabbit hole :P
sRGB/RGB is represented with 24-bits in the binary (2-base) number system, which gives us: 16,777,216 possible color values from 2^24.
This is the same as 16^6 and 256^3.
Now to explain this a bit further in detail – when we have a hexadecimal representation, we base it on a 16-base number system – and 16^2 = 256 (The hexadecimal representation consists of 2 hexadecimal characters where each represent a value from 0-15 (makes up 16 values) for each color pool Red, Green and Blue).
Hence when you see 16^6 above – this means we can have 6 hexadecimal characters where each 2 pair represent each “color pool” for Red, Green and Blue: #RRGGBB to cover all of the possible color values supposed to be covered by our 24-bit sRGB/RGB color space.
By doing this we achieve 16^6 and fill the quota of possible color values to be represented in the RGB/sRGB color space.
Now when you look at the 256^3 we can draw the conclusion that for a decimal representation of the same color space values, we can have 0-255 (counting the 0) for each one of the 3 different color pools that make up RGB – Red, Green and Blue to similarly cover all of the possible color values for our 24-bit color space of sRGB/RGB.
So for the question then of how to create hexadecimal color values from decimal numbers randing from 0-255 and vice versa, if we start with creating the hexadecimal color values it works as follows:
Say for example we have a color we want represented in hexadecimal form, which consist of 133/255 Red, 240/255 Green, 10/255 Blue – lets start with making the Red color pool into a hexadecimal representation then. Since we will reach our 256 color values by using 16^2 in hexadecimal form, we first have to understand how the 256 value is calculated in the hexadecimal representation, see below:
If we have 2 bits (which we have) the right-most bit will be Base^0 while the bit next to it to the left will be Base^1 and so on. This is how bit-representation works regardless of the base used, here we have the base 16 for hexadecimal, but its the same for base 2 for binary. See picture below demonstrating exactly how it works.
Reason for using letters instead of 10,11,12,13,14,15 for the hex value is because each bit requires 1 character – hence we cannot use the number 10 because it would require 2 characters, so therefore we use letters A-F to represent the various 2-digit values instead.
F represent 15 as max value since we count including the 0 which gives us 16 values which we want in hexadecimal representation.
In the above picture you can also get a fairly good understanding of “how much” of each “color pool” is being used for a specific color when you can weigh it against the full quota of the color pool being 255 – so in our picture above we got 249/255, which indicates that the color represented by the hex value F9 would be fairly close to MAX color value for that specific color pool – so if this color pool would be say red, then we get a fairly good idea of “how red” the part of that color would be.
For fun you can try experimenting and see what happens to the color red, the lower the color pool value you reach. Then you can try combining it with the other two color pools Green and Blue to see how they all interact with one another, there are plenty of tools online where you can try adjusting gauges and see how the hex values varies as well as the decimal color representation value to get a hint of how much of what contributes to what specific digital color. One such tool is the Colorpicker.
A fun tidbit of information regarding colors as well – according to physics the black color is the absence of color and because of this “lack” of light, it absorbs all light making it both warm in the sun but also not reflecting any wavelengths, creating no colors. If we instead look at the color white, according to physics the color white is created using the full spectrum of colors (which seems true if we look at the hexadecimal for white #FFFFFF – Full Red, Full Green, Full Blue – I like to think of F as “Full”, fitting don’t you think? :P) and this is also why white color reflects all light – because it is already fully saturated – also why white usually is the coolest color one can wear in hot summer weather.
Introduction to the Font class in Java
Java has two ways of handling fonts, either Physical or Logical.
Physical means dealing with specific Character sequence tables using a bit more advanced methods, whilst the Logical way means using the 5 predefined fonts that exist within Java that are guaranteed support throughout any and all environments.
These 5 Logical fonts are:
So if you’re fine with generally specifying the “type” of font you wish to use – say Serif/SansSerif or Monospaced fonts then this will do just fine. If you on the other hand are interested in using specific libraries I recommend that you read up on “TrueType” and how to handle specific fonts with Java.
For the purpose of this article we want our coverage of fonts to be pretty basic – so we will be creating a Font object which defines what font-family should be used: “Serif” or “SansSerif”, as well as what style the font should have using the pre-programmed/built-in constants in the Font class: Font.ITALIC (cursive), Font.BOLD or Font.PLAIN (normal) and what size the font should have (assigned in points using integer value).
You can see a practical example of creating your own Font in Java below:
// Creating a both bold and italic font and setting it to the graphic context to be used for drawings: Font boldAndItalicFont = new Font("Serif", Font.BOLD+Font.ITALIC, 36); // Notice how we use the "+"-sign to use a combination of multiple stylings graphicsContext.setFont(boldAndItalicFont); graphicsContext.drawString("bold + italic font test", 50, 120); // will draw our text string at (X,Y) position (50,120), and since the Font is set to the context, it will be used for all drawString operations on that context until its changed // Creating a bit simpler Sans-serif font: Font sansSerifFont = new Font("SansSerif", Font.PLAIN, 14);
Working with the Image class in Java
Since we deem drawing images in Java a bit more advanced, we will not cover this area in this article, instead if you’re interested we will provide you with a resource link where you can read more about it in detail.
You can read more about each of these classes respectively from the links provided in the list below:
- Graphics class on Java Oracle documentation
- Color class on Java Oracle documentation
- Font class on Java Oracle documentation
- Image class on Java Oracle documentation
Introduction to the Graphics class in Java
To draw Graphics in Java one is first required to import the Graphics class to be able to use- and access its appropriate methods for such functionality. Here’s how this is done:
The basic possibilities of drawing in 2D with Java includes not only shapes, lines and text, but also the possibility of drawing images.
A key factor to be aware of and remember when drawing 2D Graphics in Java is that every element that will be drawn, will be positioned on a “canvas” using X and Y coordinates. The “canvas” that we will be drawing on, is also known as the Graphics context.
When setting a Font or Color for the Graphics context/canvas, these Color values and Fonts will be used for everything you draw after having specified such values to the canvas.
The XY coordinate system for drawing Graphics in Java is also not quite the same as you might remember from general mathematics when working with graphs etc. but instead it works as such:
As you can see now in the image above, the X-axis works the same way as for when working with graphs in math, but the Y-axis is different – in Java it starts from the top of the canvas and increases in value the further down we get.
A useful thing to remember when trying to position your graphical elements in Java.
Setting and getting Font and color attributes of drawing context in Java
We can use the methods
.setColor() to set which Color and Font should be used for our drawings in Java.
Similarly we can check current drawing settings – which Color and Font – is already set in our drawing context by calling
.getColor() method will return a Color class object which you can read more about previously in this article, and the
.getFont() similarly will also return a Font class object which also was discussed earlier in this article.
Different types of drawing in Java with the Graphics class
There are two different types of drawing methods in Java: Draw and Fill.
Using the Graphics class Draw methods will draw elements without background color (only the outline of the element to draw), while the Fill methods will draw with background color.
Useful Drawing, Fill and Graphics methods in Java
Useful Graphics methods in Java
|.clearRect(int x, int y, int width, int height)||Clear the rectangle by filling it with the background color of the current drawing surface – can be very useful in Game Design between views|
|.getColor()||Returns the Graphics context (canvas) currently set Color object for Color to be used for drawing|
|.getFont()||Returns the Graphics context (canvas) currently set Font object for Font to be used for drawing|
|.setColor(Color c)||Set a specific Color object to be used for drawing to the Graphics context (canvas)|
|.setFont(Font font)||Sets a Font object to be used for drawing Strings to the Graphics context (canvas)|
Useful Drawing methods
|.drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer)||Used to draw images|
|.drawLine(int x1, int y1, int x2, int y2)||Draws a line using the current Color from (x1,y1) to (x2,y2) coordinates|
|.drawRect(int x, int y, int width, int height)||Draws the outlines of a specified rectangle where x and y represent the starting corner from where Java is to draw the rectangle|
|.drawString(String str, int x, int y)||Draws a String on the canvas using currently set canvas Font|
|.drawOval(int x, int y, int width, int height)||Draws an oval with specified width and height on the canvas with start in the x and y coordinates|
Useful Fill methods
|.fillOval(int x, int y, int width, int height)||Draws an oval shape and fills it with the currently set canvas Color|
|.fillRect(int x, int y, int width, int height)||Draws a rectangle and fills it with currently set canvas Color|
Practical example of how some Graphical shapes can be created can be seen below:
// Create our Graphics object that we will be working with, this variable "g" will be our Graphical context/canvas Graphics g; // Set a specific Color to our Graphics context g.setColor(Color.BLACK); // Using one of the pre-programmed static constants that exist in the Color class // Lets draw a line g.drawLine(50,80, 100,150); // This will draw a line from X=50 -> X=100 and from Y=80 -> Y=150 // Lets draw a rectangle next g.drawRect(200,200, 150,65); // This will draw a rectangle (no filling mind you) that starts from (200,200) X,Y position and has a width of 150 and a height of 65 // Next lets change the color of our Graphics context/canvas g.setColor(Color.RED); // Now lets draw a String/text g.drawString("My string drawn inside my rectangle", 200,200); // And for our Finale we will draw an Oval g.drawOval(400,400, 150,50); // This draws an oval of width 150 and height 50 starting from (400,400) X,Y position