What are the benefits to painting on a JPanel vs.

2019-02-09 02:23发布

问题:

So in a recent answer, someone commented this (in regards to painting):

"This is probably some kind of illness of 90% of Swing Programmers: When they make their own component, they always extend JPanel instead of JComponent. Why?"

I'm still fairly new to programming, so I think it's too early to call myself a Swing programmer, as I have yet to find my niche. But overriding JPanel is just the way I was taught. So I set out to find the answer to the "Why?" question of the commenter. These are some of the answers I found.


Background painting is main difference. The JComponent class doesn't paint its background, so you have to paint the background in the overridden paintComponent method. In contrast, JPanel has an opaque background which can be painted by calling its paintComponennt method.


Instead of extending JComponent, some programmers prefer to extend the JPanel class. A JPanel is intended to be a container that can contain other components, but it is also possible to paint on it. There is just one difference. A panel is opaque, which means that it is responsible for painting all pixels within its bounds. The easiest way to achieve that is to paint the panel with the background color, by calling super.paintComponent in the paintComponent method of each panel subclass:


If the opaque property is set to true ... then the Swing painting system does not have to waste time trying to paint behind the component, hence improves performance.


I think the last quote really explains it best. But besides the opacity, are there other beneficial reasons "90% of Swing programmers have this illness" of extending JPanel rather than JComponent?

回答1:

Difference in opacity handling is not the only factor.

Looking at JPanel source code helps because it is only ~100 lines.

All constructors eventually call this constructor. Opacity and double buffering default to true. The default LayoutManager is FlowLayout which you may or may not want.

public JPanel(LayoutManager layout, boolean isDoubleBuffered) {
        setLayout(layout);
        setDoubleBuffered(isDoubleBuffered);
        setUIProperty("opaque", Boolean.TRUE);
        updateUI();
}

Loy et al in O'Reilly's Java Swing 2nd edition recommend extending JComponent for truly custom components (p.1333) but also mention the need to consider a UI delegate. JPanel handles it's own concrete AccessibleContext whereas a class extending JComponent returns null.

For a read-only visual component I usually extend JComponent but I'd probably think twice for an interactive component because of the extra considerations for accessibility.

Cheers,



回答2:

This is proper mental. If you check the source of JPanel it doesn't touch opaque. However, it happens that most versions of most PL&Fs do set the opaque property. They could set other properties randomly.

Early versions of the GTK PL&F didn't set the opaqueness for JPanel. It was changed, apparently for performance though perhaps shoddy Swing programmers using JPanel inappropriately may have been a factor.

There are very few valid reasons for subclassing JPanel. Don't do it.