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. --Bob
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(Color.pink).
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); to 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."
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. --Bob
Joined: Sep 20, 2005
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.