Concepts / Random Color Generation with the HSB Model

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.

  • Programming

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.

java
Notes on the code
  • extends JPanel makes 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.

paintComponent()startsPick one of fivefontsg.setFont()Create random HSBcolorg.setColor()Compute random x andywhere the string startsDraw the messageat the chosen x and yCopies drawn so farbelow 25?Picture completeloop beginsyes, next copyno
In what order do the steps run during a single paintComponent() call, and how do the random font, color, and position choices feed into each drawn copy? The loop returns to the font choice until all 25 copies are drawn.

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.

Pattern
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.

-50smallest x value0left edge of the panelwidth - 10largest x valueincreasing xincreasing x
How does the random value map to an x-coordinate, and what are the smallest and largest x-values the formula can reach? The source states the range as -50 to width minus 10.

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

Worked example

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?

  1. 1
    Find width + 40

    400 + 40 = 440. This is the stretch factor.

  2. 2
    Multiply the random value

    0.5 * 440 = 220.0. The decimal value is between 0 and 1 scaled up to the range 0 to 440.

  3. 3
    Apply the (int) cast

    (int)220.0 = 220. The fractional part is dropped, and here there is none.

  4. 4
    Subtract 50

    -50 + 220 = 170. The string's left end starts at x = 170.

Result

x = 170. Other random values give other x values, and the smallest and largest possible results are -50 and 390 (width minus 10).

EASY

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?

  • Yes, the code is fixed, so the picture is fixed

  • No, each call to paintComponent() makes new random choices

Reveal answer
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.

Run 1 fontfont 2 of 5Run 2 fontfont 4 of 5Run 1 colorHSB color ARun 2 colorHSB color BRun 1 xx = 112Run 2 xx = 37
What is different between the first and second run? The numbers shown are illustrative values for one copy. The loop, the message, the black background, and the formulas are the same in both runs; only the random choices differ.

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 fails

    New random values are chosen on each call to paintComponent(), so the output changes from call to call.

    Do this instead

    Treat 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 like

    With the formula -50 + (int)(Math.random() * (width + 40)), a result can be negative or near the right side of the panel.

    Why it fails

    The source says the range runs from -50 to width minus 10, so copies can extend past the edges by design.

    Do this instead

    Check 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 fails

    Each pass chooses a font, then a color, then coordinates, and only then draws the string.

    Do this instead

    Trace 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.

MEDIUM

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 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.
  • 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().