Concepts / Custom Component Creation

Custom Component Creation

A custom Swing component can be defined as a subclass of JPanel, which supplies its layout, size handling, and inherited colors and fonts.

  • Programming

When No Standard Component Fits

Suppose you need a component that behaves much like a JLabel, showing a line of text, except that the text appears in mirror-reversed form. No standard Swing component does this. When the component you need does not exist, you build one yourself. This article follows one such example, a class called MirrorText, and uses it to show three things: how a custom component is assembled, how its content is painted, and where a mistake would reveal itself.

The code in this example is best read as a traceable program. Treat it as a sequence of concrete operations, one after another, rather than as a finished description of a feature. As you read, keep asking which line is responsible for each thing you see on screen.

Building the Class on JPanel

Definition

A custom Swing component can be defined as a subclass of JPanel. JPanel supplies the layout, size handling, and inherited colors and fonts that the new class receives automatically.

The MirrorText class is defined as a subclass of JPanel, and that single decision determines most of what the class inherits. It gets the panel's ability to be placed in a layout, its size handling, and its use of colors and fonts. The class then adds only what is specific to it: a constructor that receives the text to show, and a setText() method that replaces that text later. Everything else is already present because of the parent class.

JPanellayout, size handling,colors and fontsMirrorTextadds constructor andsetText()extends
What does a custom component inherit from JPanel, and where does it sit in the class hierarchy?

Tracing the Constructor and setText Call

Follow the life of one MirrorText object. The constructor receives the text to show and keeps it. Later, a call to setText() replaces that stored text with a new value. Notice that neither operation draws anything on screen by itself. The text only becomes visible when the component is painted, which is the subject of the next section.

What do you think happens?

Does MirrorText need its own field to store the background color so that it matches the panel?

  • Yes, it must store a copy of the background color

  • No, it reads the color from the JPanel it extends

Reveal answer
Answer:

No, it reads the color from the JPanel it extends

The source states that the class uses any background color, foreground color, and font set on the JPanel. Because it inherits from JPanel, it does not need its own color or font fields.

How paintComponent Produces the Visible Content

Everything the user sees inside a custom component comes from one method: paintComponent(). MirrorText overrides this method to draw its text mirror-reversed, centered within the available area. Overriding means that the class supplies its own version of the method, and the drawing logic inside that version is what determines the visible result.

Centering is not guessed. The method uses information from a FontMetrics object, which describes how large the text will be when drawn in the current font. With that size known, the text can be positioned in the middle of the component rather than at an arbitrary spot.

Key point

The visible content of a custom component is produced by overriding paintComponent(). FontMetrics tells the method how big the text is, so that the method can center it.

Before reading on, ask yourself this: if paintComponent() can draw straight onto the visible area, why would a designer need anything in between? Hold on to that question. The answer is the mirror-reversal technique, and it depends on an intermediate image.

The Off-Screen Canvas Detour

Definition

An off-screen canvas is an image that exists in memory but is not shown to the user. In the MirrorText example, it is the place where the text is first drawn.

The text is first drawn onto this image in the ordinary way, exactly as if it were being drawn normally. Nothing about the text is reversed during this first step. Only afterwards is the finished image copied onto the visible component. The reversal happens in the copy, not in the drawing.

Textthe string held byMirrorTextOff-screen canvastext drawn in normalorientationdrawImage copydestination x cornersswappedVisible panelmirror-reversed textdrawn normallyone drawing callcopied to screen
How do pixels move from the off-screen image into the visible panel, and at which step does the mirror reversal happen?

The figure shows a one-way movement. Text goes into the hidden image, and the image is then handed to the screen by a single drawing call. The component never draws the reversed text directly. It draws an image that was prepared earlier, and the copy operation is where the orientation of that image is changed.

Reading the drawImage Arguments

The copy step is performed by one command. In it, OSC names the off-screen canvas, and width and height give the size of both the component and the off-screen canvas, which are the same size. The drawImage method, as used here, takes a destination rectangle followed by a source rectangle, each given by two corners.

java
Notes on the code
  • OSC: the off-screen canvas that holds the already-drawn text
  • width, 0 and 0, height: the destination corners, in swapped order
  • 0, 0 and width, height: the source corners covering the whole canvas
Worked example

Why the destination corners flip the image

The source covers the whole off-screen image. Which direction does the destination run, and what does that do to the picture?

  1. 1
    Read the source corners

    The source corners are (0, 0) and (width, height), so the source covers the whole off-screen image from left to right.

  2. 2
    Read the destination corners

    The destination corners are (width, 0) and (0, height). The horizontal values are swapped compared with the source, so the destination runs from the right edge back to the left edge.

  3. 3
    Combine the two

    Copying the image into a region whose horizontal corners are swapped is what makes the result a mirror image.

Result

The off-screen text is copied to the screen with its left and right edges exchanged, so the visible text is mirror-reversed.

Finding the Stage Where Output Goes Wrong

A custom component has several places where its output can go wrong, and the pipeline above tells you where to look. Because the visible result is produced by a copy from an intermediate image, a mismatch between what you expect and what you see usually comes from one of three stages: the drawing into the off-screen canvas, the copy command, or the painting method that calls them.

paintComponent()overridden painting methodDraw text into canvasnormal orientationdrawImage callcorner order decides theflipScreenvisible componentcallspasses canvaspaints
In the ordered steps from paintComponent through drawing to drawImage, which step is the one where the reversed output is most likely introduced?

The reversed output is most likely introduced at the drawImage call. The drawing into the canvas happens in normal orientation, so a reversed result that appears on screen points to the copy arguments first. This is why a mistake in the copy arguments is the first place to look when the output is wrong.

  • Common mistake

    Assuming the text is reversed while it is being drawn

    What it looks like

    Looking inside the text-drawing code for a flip when the canvas is still in normal orientation

    Why it fails

    The source states that nothing about the text is reversed during the first step. The reversal happens in the copy.

    Do this instead

    Check the drawImage call first, since that is where the orientation changes.

  • Common mistake

    Expecting paintComponent() to draw reversed text directly

    What it looks like

    Trying to draw the mirrored string straight onto the visible area inside paintComponent()

    Why it fails

    The component never draws the reversed text directly. It draws an image that was prepared earlier.

    Do this instead

    Draw the text onto the off-screen canvas first, then copy the canvas with drawImage.

  • Common mistake

    Storing a separate color or font in the subclass

    What it looks like

    Adding a background color field to MirrorText and using it to paint the background

    Why it fails

    The class already uses any background color, foreground color, and font set on the JPanel it extends.

    Do this instead

    Set colors and fonts on the component itself, and let the inherited settings apply.

  • Common mistake

    Swapping destination corners by accident when editing the copy call

Practice Tracing the Copy Step

MEDIUM

A MirrorText panel shows the text correctly inside the off-screen canvas, but the visible result is still in normal orientation, not reversed. Using the three-stage view, name the stage you would inspect first and explain why. Then say which argument change would produce the mirror effect.

Hints
  • The source says the drawing into the canvas is done in the ordinary way.
  • Look at the horizontal values of the destination corners compared with the source corners.

Key Takeaways

  • A custom Swing component can be built by subclassing JPanel, which supplies layout, size handling, and inherited colors and fonts.
  • paintComponent() produces the visible content, and FontMetrics information lets the method center that content.
  • The mirror effect comes from an off-screen canvas: text is drawn normally into the canvas, then copied to the screen by drawImage.
  • The flip is produced by swapping the x corners of the destination rectangle relative to the source, so the copy arguments are the first place to check when output is wrong.