Win a copy of TDD for a Shopping Website LiveProject this week in the Testing forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
  • Campbell Ritchie
  • Paul Clapham
  • Ron McLeod
  • Jeanne Boyarsky
  • Tim Cooke
  • Liutauras Vilda
  • paul wheaton
  • Henry Wong
Saloon Keepers:
  • Tim Moores
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Frits Walraven
  • Piet Souris
  • Himai Minh

TwoButtons App From "HeadFirst Java" Book

Posts: 220
Angular Framework Ubuntu Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
For some reason I am not getting the same result from running the TwoButtons program K&B have on p. 379 of their "HeadFirst Java" book. When I run the app, I see no difference in the background of the "I'm a label" JLabel and the drawPanel. It is almost as if the line isn't working that reads: frame.getContentPane().add(BorderLayout.WEST, label);

Thanks for any hints as to what I might be doing wrong. I am a serious newbie at AWT/Swing, so I really appreciate it.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class TwoButtons {

JFrame frame;
JLabel label;

public static void main (String [] args) {
TwoButtons gui = new TwoButtons();

public void go() {
frame = new JFrame();

JButton labelButton = new JButton("Change Label");
labelButton.addActionListener(new LabelListener());

JButton colorButton = new JButton("Change Circle");
colorButton.addActionListener(new ColorListener());

label = new JLabel("I'm a label");
MyDrawPanel drawPanel = new MyDrawPanel();

frame.getContentPane().add(BorderLayout.SOUTH, colorButton);
frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
frame.getContentPane().add(BorderLayout.EAST, labelButton);
frame.getContentPane().add(BorderLayout.WEST, label);

class LabelListener implements ActionListener {
public void actionPerformed (ActionEvent event) {

class ColorListener implements ActionListener {
public void actionPerformed (ActionEvent event) {


class MyDrawPanel extends JPanel {
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;

int red = (int) (Math.random() * 255);
int green = (int) (Math.random() * 255);
int blue = (int) (Math.random() * 255);
Color startColor = new Color(red, green, blue);

red = (int) (Math.random() * 255);
green = (int) (Math.random() * 255);
blue = (int) (Math.random() * 255);
Color endColor = new Color(red, green, blue);

GradientPaint gradient = new GradientPaint(70,70,startColor, 150,150, endColor);

[ October 26, 2005: Message edited by: Bob Nedwor ]
[ October 26, 2005: Message edited by: Bob Nedwor ]
Posts: 976
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well if you can read the text "I'm a label" (or "Ouch") then
the frame.getContentPane().add(BorderLayout.WEST, label) line
is indeed working.

There are two reasons you see no difference in the backgrounds
of the JLabel and the drawPanel. The first is that the JLabel
defaults to isOpaque()==false, so it doesn't paint its background
and the background color of the frame's contentPane shows through.
You can change this by calling label.setOpaque(true).

The second reason is that (at least in my LnF) that the background
of the opaque JLabel happens to be the same color as the apparent
background of the drawPanel, so there is no visible difference.
You can change this by calling label.setBackground(

I say the "apparent" background of the drawPanel because the
drawPanel isn't opaque either, so the background you see is
that of the contentPane showing through.
Theoretically, you should be able to call drawPanel.setOpaque(true)
and drawPanel.setBackground(Color.yellow), but this won't work because
the author of this code has overridden paintComponent() in such a
way that the value of isOpaque() is ignored. The drawPanel is
effectively always transparent.

This was not wise on the author's part, IMHO, as the javadocs for
paintComponent() say "Further, if you do not invoker super's
implementation you must honor the opaque property, that is if this
component is opaque, you must completely fill in the background in
a non-opaque color. If you do not honor the opaque property you will
likely see visual artifacts."
As they hint, an easy way to fix this is to add a call to super.paintComponent(g) as the first line of drawPanel's paintComponent().

If I were the author if this code, I would probably also change
frame.getContentPane().add(BorderLayout.xxxx, yyyy);
frame.getContentPane().add(yyyy, BorderLayout.xxxx);

It will work as written, but the javadocs for add(String, Component)
say "This method is obsolete as of 1.1. Please use the method
add(Component, Object) instead."
Bob Nedwor
Posts: 220
Angular Framework Ubuntu Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Brian, Thanks for the explanation. I just realized that it works better using the paintComponent method that was 14 pages back on p. 365, rather than the one that was only 12 pages back on 367. Unless I missed something else, this was not entirely clear..

But the new one does have the line:
g.fillRect(0,0,this.getWidth(), this.getHeight());

and works much better. Thanks so much.
Brian Cole
Posts: 976
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I can't look at the code on page 367 because I don't have the book.
In fact, I had never heard of "HeadFirst Java" before your posting
yesterday. Looking it up on the web, I see that it is an O'Reilly
book with a nontraditional approach. I'll have to check it out next
time I have some free time in a book store.

Anyway, a plain g.fillRect(0,0,this.getWidth(), this.getHeight())
is not necessarily what you want because (in the absence of an
enclosing if clause) the panel will be permanently opaque.

If I were to rewrite MyDrawPanel, I might do it like this:

But if I were the author of "HeadFirst Java" I wouldn't necessarily
do it this way. It would depend on what the I was trying to do with
this example.
Well THAT's new! Comfort me, reliable tiny ad:
Free, earth friendly heat - from the CodeRanch trailboss
    Bookmark Topic Watch Topic
  • New Topic