Colors and the Color Class in Java
A transparent color is a Color object created with an alpha component, which controls its opacity; an ordinary three-argument RGB color is fully opaque.
A Color That Lets Shapes Show Through
Most colors you have used so far in Java are solid. When you draw with them, whatever you paint replaces what was underneath. Sometimes you want the opposite: a shape that lets the shapes beneath it show through. Java handles this with colors that carry an alpha component. This article starts from a small program that builds transparent colors and asks you to reason about what each color will look like, then explains the rules that make those predictions work.
Keep one question in mind as you read: when a program uses a transparent color, which line decides how opaque the color is? By the end of the article you should be able to answer that question, and the same habit will help you find the exact line where a result stops matching your expectation.
What the Alpha Component Controls
Colors with alpha components were introduced in Java along with Graphics2D, but they can also be used with ordinary Graphics objects. The alpha component is the part of a color that controls its opacity. Opacity describes how much of the drawing underneath a color shows through it. A higher alpha value makes the color more opaque, so less of what lies beneath is visible. A lower alpha value makes it more transparent, so more of the underlying drawing shows through.
A transparent color is a Color object created with an alpha component, which controls its opacity. An ordinary three-argument RGB color is fully opaque.
Read the top row of the figure first. A fully opaque red overlay covers the blue background in the region it occupies, so the blue is replaced and only red is visible there. Now read the bottom row. The same red shape is semi-transparent, so the blue beneath it still reaches your eye and the visible result is a mixture of the two. Nothing about the shape changed except its alpha value. That single number is what separates a solid replacement from a see-through overlay.
Tracing What setColor Does
Once a transparent color exists, you use it exactly the way you use any other color. The source describes this with a Color named c and a graphics context named g. Calling g.setColor(c) sets the color for subsequent drawing, and this is the same mechanism used for opaque colors. The color is a piece of state held by the graphics context. It stays in effect until another setColor call replaces it.
Follow the figure from top to bottom. The Color c is created once and then passed to setColor, which makes it the active color. The fillRect call that comes next draws with c, so the transparency of c applies to that shape. The active color does not switch back on its own. It changes only when another setColor call runs, which is why the second fillRect in the figure uses a different color. When you trace a program, track the active color as a value that moves forward line by line, not as something tied to the variable name c.
Two Alpha Scales Compared
The Color class offers two constructors that accept an alpha component. Both take four parameters: three color channels and one alpha value. The forms differ in the kind of number they expect. The first uses integers, and the second uses floating-point numbers. Read a constructor call from left to right. The first three arguments set the red, green, and blue channels, and the last argument sets the alpha component. The alpha argument is the last position in both forms, and its range matches the range of the other three arguments for that constructor.
The two columns in the figure describe the same range of opacity written in two different number styles. The integer form runs from 0 to 255, and the float form runs from 0.0 to 1.0. The endpoints match: the lowest value on each scale is the most transparent setting, and the highest value is fully opaque. The middle values also correspond. The integer alpha of 200 is the first color in the source, described as slightly transparent. The float alpha of 0.5 is the second color, described as 50 percent opaque. Those two numbers are written differently, but each one is read against its own scale.
The float form lets you think in percentages. A value of 0.5 is a half, which is exactly the 50 percent figure the source gives. That is the main reason to prefer the float form when your reasoning is already about proportions. The integer form fits better when you are working with values that are already in the 0 to 255 range.
Predicting the Default Alpha
The three-argument constructor creates a color with only red, green, and blue values, so no alpha value appears in the call. Before reading the answer, commit to a prediction about the opacity that Java gives such a color.
What do you think happens?
A color is created with Color(255, 0, 0) and no alpha argument. Is it transparent, semi-transparent, or fully opaque?
Reveal answer
Fully opaque
An ordinary three-argument RGB color is fully opaque. On the integer scale from 0 to 255 that corresponds to the top value, 255. The alpha is not written in the call, but the color is still solid, which is why the three-argument constructor produces the same kind of color you have used all along.
The reasoning is simple once you know the rule. A three-argument color has no transparency set by the program, so it is fully opaque. To make a color transparent, you must use one of the four-argument constructors and choose an alpha value that is less than fully opaque. The three-argument call is the signal that the color should be solid.
Worked Example: Two Constructors Side by Side
- Line 1: integer form, red 255, green 0, blue 0, alpha 200 on the 0 to 255 scale. This is the source's transparent red.
- Line 2: float form, red 0.0, green 0.5, blue 0.5, alpha 0.5 on the 0.0 to 1.0 scale. This is the source's blue-green color at 50 percent opacity.
- Lines 3 and 4:
setColormakes t the active color, and the nextfillRectdraws with it. - Lines 5 and 6:
setColorreplaces the active color with u, and the followingfillRectdraws with it.
Reading each constructor call against its own range
Two colors are created, one with integer arguments and one with float arguments. For each call, state the alpha value on the scale it uses and say how opaque the color is.
- 1Check the last argument first
In the first call the alpha argument is 200. Because the arguments are integers, the alpha scale is 0 to 255.
- 2Confirm the other arguments fit the range
The red value 255 is the top of the 0 to 255 range, and the green and blue values are 0, which also fall inside it. The call is valid.
- 3Interpret the integer alpha
An alpha of 200 is near the top of the integer scale, so the red is slightly transparent.
- 4Check the float call the same way
In the second call the alpha argument is 0.5, and the arguments are floats, so the alpha scale is 0.0 to 1.0. All four values fall inside that range.
- 5Interpret the float alpha
An alpha of 0.5 is a half, so the blue-green color is 50 percent opaque.
The integer call gives a slightly transparent red. The float call gives a blue-green color at 50 percent opacity. Each value was read against the scale of its own constructor form.
Locating the Failing Line
When a transparent-color program produces a result you did not expect, do not start by asking whether the whole program is wrong. Move line by line and stop at the first line where the stored value differs from your prediction. That line is the failure location. For each line, ask two questions: which value is being stored, and does that value fall inside the range the constructor requires? Most surprising results trace back to one of those two questions, and the cause is almost always in the arguments on that line or in the choice of constructor.
Common mistake Using the integer alpha scale when the float scale was intended
What it looks likeColor c = new Color(1.0f, 0.0f, 0.0f, 1); ... the alpha 1 is an integer, but the other arguments are floats, which does not match the float constructor's expected types.
Why it failsThe alpha argument must follow the same number type and range as the other three arguments for that constructor. Mixing styles breaks the rule that all four positions use one scale.
Do this insteadUse the float form with 1.0f for full opacity, or use the integer form with 255 for full opacity, and keep all four arguments in the same style.
Common mistake Reading an integer alpha of 1 as almost opaque
What it looks likeColor c = new Color(255, 0, 0, 1); the red is intended to be solid.
Why it failsOn the 0 to 255 scale, an alpha of 1 is at the very bottom of the range, so the color is nearly fully transparent. It is not nearly fully opaque.
Do this insteadFor a solid color on the integer scale, the alpha should be 255. Check the scale before you read the number.
Common mistake Assuming a three-argument color is transparent
Why it failsA three-argument RGB color is fully opaque, so the program draws a solid shape regardless of what was drawn underneath.
Common mistake Assuming setColor resets after one draw call
Why it failsThe active color stays in effect until another
setColorcall replaces it. A later shape can use a transparent color simply because no new color was set after it.
Practice Tracing Transparent Colors
A program creates Color a = new Color(0, 0, 255, 128) and Color b = new Color(0.0f, 0.0f, 1.0f, 0.25f), then calls g.setColor(a), draws a rectangle, calls g.setColor(b), and draws a second rectangle. Which rectangle is more opaque, and what is the alpha of each color on its own scale?
Hints
- Identify which constructor each color uses by checking whether the arguments are integers or floats.
- Find the scale that matches the alpha argument in each call before deciding how opaque it is.
- Remember that
setColorchanges the active color, so the second rectangle uses b, not a.
Write a constructor call for a color with red 255, green 255, blue 0 that is 75 percent opaque, once using the integer form and once using the float form. Then state which alpha value you used on each scale.
Hints
- On the float scale, 75 percent corresponds to 0.75.
- On the integer scale from 0 to 255, multiply the fraction by 255 to find the matching alpha.
Key Takeaways
- The alpha component of a Color controls its opacity: a higher alpha makes it more solid, and a lower alpha lets more of the underlying drawing show through.
- The Color class has two four-argument constructors. The integer form uses 0 to 255 for alpha, and the float form uses 0.0 to 1.0, and the alpha argument follows the same range rule as the color channels.
- A three-argument RGB color has no transparency and is fully opaque, so transparency only appears when a four-argument constructor sets a lower alpha.
- Passing a color to g.setColor makes it the active color for later drawing calls until another
setColorreplaces it, so a transparent color is used exactly like any other color. - When a result is unexpected, trace the program line by line, check the stored value and its range on each line, and stop at the first line that disagrees with your prediction.