Drawing Text in Java Graphics
Every graphics context has a current font, which is used for drawing text through that context.
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.
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
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.
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.
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.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.
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.
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.
- The first
setFont()call changes the component's own font. - The second
setFont()call changes only the current font of the graphics context g.
| Aspect | component.setFont(font) | graphics.setFont(font) |
|---|---|---|
| Object changed | The component | The graphics context |
| Font it affects | The component's associated font | The graphics context's current font |
| Where it takes effect | Sets the starting font for graphics contexts created on that component | Affects text drawn through that graphics context afterward |
| Retrieved with | component.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 likeA 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 failsThe component's font is the starting point for graphics contexts. The current font of an existing graphics context is a separate setting.
Do this insteadCall 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 failsThe graphics context's current font is its own state, and the component keeps its own associated font.
Do this insteadUse 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 likeA paint method sets a bold font and later code in the same method assumes the original font is still current.
Why it failsOnce
setFont()is called, the current font changes for text drawn afterward through that graphics context.Do this insteadSave the font with getFont() before changing it, and restore the saved Font with setFont() when finished.
Checking Your Understanding of Font Ownership
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
drawStringcall happens before or after any change to g's font.
Keeping the Two Fonts Straight
- 1Every graphics context has a current font, and that font is used for text drawn through the context.
- 2
getFont()returns the current font as a Font object, andsetFont()changes it for text drawn afterward. - 3When a graphics context is created for drawing on a component, its current font starts equal to the component's font.
- 4
component.setFont(font)changes the component's font, whileg.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, andgetFont()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)andgraphics.setFont(font)change different objects, so check which object you are changing.