Random Color Generation with the HSB Model
A JPanel subclass such as RandomStringsPanel draws its content inside the paintComponent() method, which the source describes as the place where all of the panel's drawing is done.
A Picture That Never Repeats Itself
This lesson is built around a program that draws the same short message many times on a black background. Each copy of the message looks different. Before reading how the program works, it helps to run it and watch what changes from one copy to the next. Notice which features vary: the letter shapes, the colors, the sizes, and the places where the copies land. Then ask which of those you could predict in advance and which you could not.
The panel in this example is called RandomStringsPanel. It is a drawing surface rather than a finished application. Everything it shows is produced by one method, paintComponent(), and all of the randomness comes from a small number of choices made inside that method. Keeping that structure in mind will help you find the source of any unexpected result later.
Why a Panel Needs a Subclass
In Swing, a JPanel is a general-purpose container that can be placed in a window. By itself, a JPanel does not show anything specific. To make a panel display something, you write a subclass of JPanel and override the method named paintComponent(). The source describes this method as the place where all of the drawing for the panel is done. Your class inherits everything a JPanel does, and you add only the part that is unique to your panel.
- extends
JPanelmakes this class a panel subclass that inherits panel behavior - import
java.awt.* brings in drawing types such as Graphics paintComponent(Graphics g)is the overridden method where the drawing happens- The body shown here is an illustrative skeleton; the drawing loop is described in the next section
The extends keyword is the link that makes RandomStringsPanel a JPanel subclass. It gets the behavior of a panel and specializes it. The Graphics object that paintComponent() receives is the tool the method uses to draw. The class header and the method together define the whole panel.
Tracing One Pass Through the Loop
The source describes paintComponent() as drawing 25 copies of the message. For each copy, the method makes three independent random choices and then draws the string. The first choice is a font, picked at random from five predefined fonts that differ in size and style. The second choice is a color, created as a random HSB color and applied with g.setColor(). The third choice is a location, made of random x and y coordinates that say where the left end of the string starts.
The order matters. A font is selected on the Graphics object with g.setFont(), a color is selected with g.setColor(), and only then is the message drawn at the chosen coordinates. The Graphics object holds the current settings, so each setting applies to the drawing that follows it. Each of the 25 passes through the loop starts with fresh random choices and ends by drawing one copy.
The diagram shows that the four random choices (font, color, x, and y) are independent inputs to a single drawing step. A change to any one of them changes that copy, and none of them depends on the others. The loop repeats the step 25 times, so the final picture is a stack of 25 copies drawn over the black background.
Reading the X-Coordinate Formula
The x coordinate is the part of the position logic that most deserves a careful read. The source gives the formula as follows.
x = -50 + (int)(Math.random() * (width + 40))Read the formula from the inside out. Math.random() produces a floating-point value between 0 and 1. Multiplying it by (width + 40) stretches that value across a range slightly wider than the panel. The (int) cast turns the decimal into a whole number by dropping the fractional part. Finally, subtracting 50 shifts the whole range to the left.
The source says this produces a random integer in the range from -50 to width minus 10. Because the left end of the string can sit at a negative x value or near the right side of the panel, the string is allowed to extend beyond the left or right edge. The source says the formula for y works in the same way, so strings can also extend beyond the top and bottom. The design is deliberate: the panel should work no matter what size it is, and letting copies spill past the edges keeps the composition from looking like a neatly bounded box.
Worked Example: Computing One x Value
Finding x for a panel 400 pixels wide
The panel width is 400. Math.random() returns 0.5 on one pass. What x value does the formula produce, and where does the string start?
- 1Find width + 40
400 + 40 = 440. This is the stretch factor.
- 2Multiply the random value
0.5 * 440 = 220.0. The decimal value is between 0 and 1 scaled up to the range 0 to 440.
- 3Apply the (int) cast
(int)220.0 = 220. The fractional part is dropped, and here there is none.
- 4Subtract 50
-50 + 220 = 170. The string's left end starts at x = 170.
x = 170. Other random values give other x values, and the smallest and largest possible results are -50 and 390 (width minus 10).
Using the same formula, a panel is 300 pixels wide and Math.random() returns 0.25. Compute x. Then decide whether the value you found falls within the range -50 to width minus 10.
Hints
- First compute width + 40.
- Multiply that by 0.25, then drop the fractional part before subtracting 50.
Why Two Runs Look Different
What do you think happens?
If you run RandomStringsPanel twice without changing any code, will the two pictures match?
Reveal answer
No, each call to paintComponent() makes new random choices, so the pictures differ.
Because new random values are used each time paintComponent() runs, a different picture is drawn on each call. The source describes this as the intended behavior, not a defect, and it is the reason the source calls the style poor.
The fixed parts are the code itself: the five predefined fonts, the loop that runs 25 times, the HSB color step, the x and y formulas, and the black background. The random parts are the font chosen, the color created, and the coordinates computed on each pass. Since those random parts are re-chosen each time paintComponent() runs, the second picture differs from the first even though nothing in the source changed.
Mistakes Beginners Make With This Panel
Common mistake Expecting the same picture every time the program runs
Why it failsNew random values are chosen on each call to
paintComponent(), so the output changes from call to call.Do this insteadTreat each run as a new sample of the same random design, and look for the fixed rules instead of the particular picture.
Common mistake Thinking the x formula keeps every copy inside the panel
What it looks likeWith the formula -50 + (int)(Math.random() * (width + 40)), a result can be negative or near the right side of the panel.
Why it failsThe source says the range runs from -50 to width minus 10, so copies can extend past the edges by design.
Do this insteadCheck the stated range instead of assuming the panel boundaries limit the output.
Common mistake Assuming the font, color, and position are chosen in a different order than the code shows
Why it failsEach pass chooses a font, then a color, then coordinates, and only then draws the string.
Do this insteadTrace one pass in code order to find where a surprising result was produced.
Common mistake Assuming the vertical position is chosen by a different rule than the horizontal one
Locating a Surprising Result
When a copy looks unexpected, a useful check is to ask whether your explanation names a specific formula or step. Horizontal placement is controlled only by the x formula, so a reasonable explanation of an unusual horizontal position points there. Vertical placement is controlled by the analogous y formula, which the source describes but does not spell out in full, so an explanation of vertical placement should refer to that y logic rather than guess at a formula.
Run RandomStringsPanel, pick one copy of the message that lands partly off the panel, and explain in one or two sentences which random choice placed it there and why it was allowed to extend past the edge.
Hints
- Look at which coordinate would place the string outside the panel.
- Recall the range -50 to width minus 10 for x.
Key Takeaways
- A
JPanelsubclass such asRandomStringsPaneldraws its content inside thepaintComponent()method, which the source describes as the place where all of the panel's drawing is done. - Each call to
paintComponent()draws 25 copies of the message, and each copy gets a random font from five predefined fonts, a random HSB color, and random x and y coordinates. - The x formula -50 + (int)(
Math.random()* (width + 40)) produces values the source describes as ranging from -50 to width minus 10, so copies can extend past the panel's edges. - Different pictures on different runs are the intended behavior, because new random choices are made on each call to
paintComponent().