The specification of the operation "paintComponent" as
implemented by an object of the class "JComponent" is given in
[1]. In few words it is:
[2] Calls the UI delegate's paint method, if the UI
delegate is non-null.
This means, that a method "m" can depend on this behavior, if
it accepts a JComponent:
void m( JComponent jc ){ (...) jc.paintComponent(g); }
By the specification [1] the Method "m" now can assert that
the Invocation will "call the UI delegate's paint method, if
the UI delegate is non-null."
Often, it is suggested to overwrite the method "paintComponent"
for doing custom painting. But then the description [2] of the
operation might not apply anymore. I.e., if the method is
overwritten, the new implementation as seen in textbooks often
will /not/ call the UI delegate's paint method - thus breaking
the contract [2] of the class JComponent. Then, such
overwriting of paintComponent should be dispraised.
Is this interpretation correct?
[1]
http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/JComponent.html
Chris Smith - 06 Feb 2004 14:47 GMT
> The specification of the operation "paintComponent" as
> implemented by an object of the class "JComponent" is given in
> [1]. In few words it is:
>
> [2] Calls the UI delegate's paint method, if the UI
> delegate is non-null.
Unfortunately, the meaning of this is ambiguous. There's a difference
between defining the behavior of a specific class's implementation, and
defining the contract of a method. Generally, when the API docs intend
to specifically define a contract for a method that's declared in a
class (as opposed to an interface where defining a contract is all
that's possible), they say so specifically. In this case, the specific
comments about overriding the method specifically imply that the default
behavior is not to be interpreted as a contract.
> Often, it is suggested to overwrite the method "paintComponent"
> for doing custom painting.
Actually, it's "override". There is no such thing as "overwriting" a
method, unless you mean when happens when you accidentally kit the
insert key mode in your editor and then start typing. :)
I think it's certainly still valid to suggest overriding paintComponent
in a subclass if the appearance is designed to be independent of the
look and feel. Only fairly widespread or common components have a
platform-specific look and feel; it's simply not reasonable or helpful
to expect everyone to write subtly different code to draw a completely
unfamiliar UI component on each major platform. If you intend to
provide an implementation that is specific to a given look and feel, of
course, then you should do it in the UI delegate.
> But then the description [2] of the
> operation might not apply anymore. I.e., if the method is
[quoted text clipped - 4 lines]
>
> Is this interpretation correct?
No, I don't think so, for the reasons above.

Signature
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.
Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
Stefan Ram - 06 Feb 2004 15:12 GMT
> In this case, the specific
>comments about overriding the method specifically imply that the default
>behavior is not to be interpreted as a contract.
I see, thank you!
Thomas Weidenfeller - 06 Feb 2004 15:52 GMT
> The specification of the operation "paintComponent" as
> implemented by an object of the class "JComponent" is given in
> [1]. In few words it is:
Few? Boy, you are really in academics, aren't you? So many words for a
simple question :-). Which is:
"If someone overrides paintComponent(), must he ensure (add code so)
that the UI delegate is still called?"
Short answer:
Yes, but ...
Medium answer:
... most people doing some custom painting don't run into problems with
no longer invoking the UI delegate, because they don't alter existing
sophisticated components, but just draw everything on a JComponent or
JPanel. These two have rather limited or no UI delegates at all.
Also, these custom components are usually not widely reused, so
potential shortcomings in radical different environments are not recognized.
Long answer:
Last time I checked, JComponent didn't have a UI delegate at all, or it
was doing nothing (don't remember).
-> Conclusion: If you use a JComponent as a base class for your custom
painting, the UI delegate doesn't matter at all.
Further down in the class hierarchy it is JPanel where one finds the
first UI delegate.
JPanel's UI delegate doesn't do much. It is just there to fulfill the
promise of the opaque attribute.
The opaque attribute is commonly misunderstood. Its primary purpose
isn't to flip a component's background between
transparent/nontransparent. That is just a side-effect of some
components. It is a promiss by the component. Depending on what
getOpaque() returns, it promises to completely paint everything within
its bounds, or not. A component which accepts changes to the attribute
via setOpaque() must therefore change its behavior when painting.
And now it gets interesting. JComponent doesn't keep its opaque promis.
You can flip the attribute, but it doesn't change its behavior. JPanel
does follow the attribute. Its UI delegate is observing the flag and
either fills the background with the background color, or does nothing.
-> Conclusion: If you use a JPanel, the UI delegate doesn't matter much.
You break the opaque contract, but as long as you paint everything
yourself there is a good change that no one will notice.
-> Conclusion: If you plan to provide a reusable component doing some
custom painting, and if you want to support the opaque attribute (a)
consider using JPanel, not JComponent, as the base class, and (b) invoke
super() (which will invoke the UI delegate, which will check the opaque
attribute and fill or not fill the background) before you do your own
drawings.
-> Conclusion: If you use JComponent as base class, either check the
current value of the opaque attribute yourself, or at least ensure that
getOpaque() does return the correct value, and that setOpaque() is ignored.
For any class deeper down in the JComponent hierarchy it entirely
depends on the complexity of the UI delegate if someone notices the
breaking of the contract or not.
Most tutorials on custom painting suggest to start with a JPanel or a
JComponent. There is little impact of a contract breach with any of
these two as a base class. So it is indeed often forgotten that one
should better call the UI delegate (via a simple call to super()) if one
tries to mess with more complex components than JPanel/JComponent
/Thomas