Concepts / Drawing Text in Java Graphics

Drawing Text in Java Graphics

Every graphics context has a current font, which is used for drawing text through that context.

  • Programming

Predicting Which Font Text Uses

When a program draws text on the screen, the letters need a shape, size, and style. In Java graphics, that information comes from a font. This article answers a practical question: when your code draws text, which font does it use, and how can you control that choice? The answer depends on an object called a graphics context, and on the font that belongs to the component where the drawing happens.

EASY

Before reading on, predict this. A program gets a graphics context for a panel, calls setFont() on that graphics context with a bold font, draws some text, and then draws more text. Does the second piece of text use the bold font? Does the panel's own font change? Write down your answer before continuing.

Hints
  • Think about which object the setFont() call was made on.
  • Ask whether the change should affect text drawn afterward or text drawn before the call.

The Current Font of a Graphics Context

Definition

Every graphics context has a current font, which is used for drawing text through that context.

The current font is the font that the graphics context applies to text it draws. It is part of the state of the graphics context, not a property of the text itself. When you ask a graphics context to draw text, it uses whatever its current font is at that moment.

A graphics context exposes two methods for this font. setFont() on a graphics context changes its current font for text drawn afterward. getFont() returns that current font as a Font object. Because getFont() returns the actual font in use, you can save it, change the font, and restore the saved font later.

ComponentComponent fontCurrent fontGraphics contexthasprovides drawing surfacehas
Which object owns which font? The component holds its own font, and the graphics context used to draw on that component holds a separate current font.

Tracing setFont and getFont

The following code is an original illustration of the rule above. It saves the current font with getFont(), changes it with setFont(), and then restores the saved font. Read it line by line and track which font is current at each drawString call.

java
Output
Starting text is drawn in the font the graphics context started with. Bold text is drawn in SansSerif bold at size 18. Back to original is drawn in the starting font again.
Notes on the code
  • getFont() returns the current font as a Font object, so it can be stored in a variable.
  • setFont() changes the current font of this graphics context for text drawn afterward.
  • Restoring the saved Font object with setFont(original) returns the context to its earlier state.
Starting fontcurrent font when contextwas createdBold 18after setFont with new boldfontStarting font againafter setFont with savedfontsetFont(new bold font)setFont(original)
After setFont() is called on a Graphics object, what is the font state before and after, and does the change affect later drawing calls? The current font moves from the starting font to the bold font and then back to the starting font, and each drawString call uses the font current at that moment.

Where a Graphics Context Gets Its Starting Font

A graphics context is not created in isolation. When a graphics context is created for drawing on a component, its current font starts equal to the component's font. So the component's font is the starting point, and a later setFont() call on the graphics context can override it for the text drawn through that context.

Component fontfont set on the componentGraphics contextcreatedfor drawing on thecomponentStarting current fontequal to the component fontText drawnuses the current fontsupplies starting fontcurrent font starts asdrawing uses
How does the font flow from the component into the Graphics object that getGraphics() or paint() provides, and where does that flow start? The flow starts at the component's font and is copied into the new graphics context as its initial current font.

Setting the Component Font Versus the Graphics Font

Components have their own associated font, set with component.setFont(font). The graphics context has a separate current font, changed with setFont() on the Graphics object. The two calls look almost identical, which is why they are easy to confuse. The table below lines them up so you can see which object each call changes and when each setting matters.

java
Notes on the code
  • The first setFont() call changes the component's own font.
  • The second setFont() call changes only the current font of the graphics context g.
Aspectcomponent.setFont(font)graphics.setFont(font)
Object changedThe componentThe graphics context
Font it affectsThe component's associated fontThe graphics context's current font
Where it takes effectSets the starting font for graphics contexts created on that componentAffects text drawn through that graphics context afterward
Retrieved withcomponent.getFont()getFont() on the graphics context

Two settings that are easy to mix up

Mistakes Beginners Make With Fonts

  • Common mistake

    Calling setFont() on the component and expecting a font change in the middle of a paint method

    What it looks like

    A component font is set, but the code expects a single drawString call to use a different font without calling setFont() on the graphics context.

    Why it fails

    The component's font is the starting point for graphics contexts. The current font of an existing graphics context is a separate setting.

    Do this instead

    Call setFont() on the Graphics object g when text drawn through that context should use a different font.

  • Common mistake

    Assuming a setFont() call on the graphics context changes the component's font

    Why it fails

    The graphics context's current font is its own state, and the component keeps its own associated font.

    Do this instead

    Use component.setFont(font) to change the component's font, and g.setFont(font) to change only the drawing context.

  • Common mistake

    Changing the graphics font and never restoring it

    What it looks like

    A paint method sets a bold font and later code in the same method assumes the original font is still current.

    Why it fails

    Once setFont() is called, the current font changes for text drawn afterward through that graphics context.

    Do this instead

    Save the font with getFont() before changing it, and restore the saved Font with setFont() when finished.

Checking Your Understanding of Font Ownership

MEDIUM

A component has the font Serif 16. A graphics context is created to draw on that component. Then g.setFont(new Font("SansSerif", Font.BOLD, 18)) is called, and drawString is called. Then the program calls drawString again without changing the font. Which font does each drawString call use, and what is the component's font after all of this?

Hints
  • Start by identifying the font the graphics context begins with.
  • Remember that setFont() on g changes only the graphics context's current font.
  • Ask whether the second drawString call happens before or after any change to g's font.

Keeping the Two Fonts Straight

  1. 1
    Every graphics context has a current font, and that font is used for text drawn through the context.
  2. 2
    getFont() returns the current font as a Font object, and setFont() changes it for text drawn afterward.
  3. 3
    When a graphics context is created for drawing on a component, its current font starts equal to the component's font.
  4. 4
    component.setFont(font) changes the component's font, while g.setFont(font) changes only the current font of that graphics context.

Key Takeaways

  • Every graphics context has a current font, which is used for drawing text through that context.
  • setFont() on a graphics context changes its current font for text drawn afterward, and getFont() returns it as a Font object.
  • A component has its own font, and a graphics context created for drawing on that component starts with a current font equal to the component's font.
  • component.setFont(font) and graphics.setFont(font) change different objects, so check which object you are changing.