-
Enhancement
-
Resolution: Unresolved
-
P4
-
8
-
generic
-
generic
A DESCRIPTION OF THE PROBLEM :
I had a bunch of trouble getting JLayer to work. Specifically, I couldn't get anything on the glass pane to show up at all. It turns out I was being put wrong by the documentation.
The Javadoc of public instance method `JLayer.createGlassPane()` says:
"Called by the constructor methods to create a default glassPane. By default this method creates a new JPanel with visibility set to true and opacity set to false."
Let's test the documentation's claim that the glass pane is visible "by default":
System.out.println(new JLayer<>().createGlassPane().isVisible()); // true
System.out.println(new JLayer<>().getGlassPane().isVisible()); // false
Huh. Okay, so that's unintuitive. The `createGlassPane()` method *technically* does return a visible glass pane, but checking the source we see it is always made invisible by the very constructor which calls it!!!
public JLayer(V view, LayerUI<V> ui) {
setGlassPane(createGlassPane());
setView(view);
setUI(ui);
}
/**
* Sets the {@code JLayer}'s glassPane component, which can be {@code null}.
* <br>This is a bound property.
*
* @param glassPane the glassPane component of this {@code JLayer}
*
* @see #getGlassPane()
*/
public void setGlassPane(JPanel glassPane) {
Component oldGlassPane = getGlassPane();
boolean isGlassPaneVisible = false;
if (oldGlassPane != null) {
isGlassPaneVisible = oldGlassPane.isVisible();
super.remove(oldGlassPane);
}
if (glassPane != null) {
glassPane.setMixingCutoutShape(new Rectangle());
glassPane.setVisible(isGlassPaneVisible);
super.addImpl(glassPane, null, 0);
}
this.glassPane = glassPane;
firePropertyChange("glassPane", oldGlassPane, glassPane);
revalidate();
repaint();
}
So, JLayer's glass pane is always initially invisible, due to the bizarre visibility-copying behavior in `setGlassPane`. Easy once you know what's going on, but the documentation doesn't *tell* you what's going on. On the contrary, the only vaguely relevant thing it says is "with visibility set to true". Only digging in the source code reveals the truth.
Problems here:
* `createGlassPane()` method: The wording says the glass pane is visible by default, which is *technically* correct but misleading. Also, the wording very much makes it sound like it is designed to be overridden by subclasses, but JLayer is final!! So the only reason for the method to be public is to manually call it, but the documentation doesn't suggest why one should ever need to do so. (I can make my own JPanel, thank you very much.)
* `setGlassPane` method: Why does it copy the visibility of the old glass pane? Why does it assume the glass pane should be invisible by default? WHY ISN'T THAT BIZARRE VISIBILITY-COPYING BEHAVIOR DOCUMENTED AT ALL? THAT IS ABSOLUTELY POINT-BLANK NOT OKAY. When I tried creating my own JPanel, manually forced it visible, and manually set it as the glass pane, it AGAIN got quietly forced invisible because of this bizarre visibility-copying behavior.
* Unspecified: What is the intended use of the glass pane? It can be guessed that the JLayer glass pane behaves similarly to the JRootPane glass pane (i.e., components on the glass pane are painted above other components), but it doesn't technically say that. It doesn't say that anywhere.
* Unspecified: Is the glass pane painted at all by the default LayerUI class, or must we subclass (as suggested by the class documentation) and implement that painting ourselves? (That was another one of the things I tried.)
* Unspecified: Is the glass pane *only* for painting over the view (no), or can components on the glass pane also receive input events? (Yes) Can glass pane components receive keyboard focus? (Yes) Can they interact with drag and drop? (Yes) Those are good features and should be documented!
* Incomplete and broken tutorial: The official JLayer tutorial at https://docs.oracle.com/javase%2Ftutorial%2Fuiswing%2F%2F/misc/jlayer.html doesn't mention the glass pane whatsoever. Also, all the images on that page are 404; I had to go get it from the Wayback Machine.
* No other official documentation ever refers to the JLayer glass pane functionality or describes what it does in any way. The sum and total documentation for this feature is that it's "a new JPanel with visibility set to true and opacity set to false", and it "can be null". Hopelessly incomplete and inadequate!
I had a bunch of trouble getting JLayer to work. Specifically, I couldn't get anything on the glass pane to show up at all. It turns out I was being put wrong by the documentation.
The Javadoc of public instance method `JLayer.createGlassPane()` says:
"Called by the constructor methods to create a default glassPane. By default this method creates a new JPanel with visibility set to true and opacity set to false."
Let's test the documentation's claim that the glass pane is visible "by default":
System.out.println(new JLayer<>().createGlassPane().isVisible()); // true
System.out.println(new JLayer<>().getGlassPane().isVisible()); // false
Huh. Okay, so that's unintuitive. The `createGlassPane()` method *technically* does return a visible glass pane, but checking the source we see it is always made invisible by the very constructor which calls it!!!
public JLayer(V view, LayerUI<V> ui) {
setGlassPane(createGlassPane());
setView(view);
setUI(ui);
}
/**
* Sets the {@code JLayer}'s glassPane component, which can be {@code null}.
* <br>This is a bound property.
*
* @param glassPane the glassPane component of this {@code JLayer}
*
* @see #getGlassPane()
*/
public void setGlassPane(JPanel glassPane) {
Component oldGlassPane = getGlassPane();
boolean isGlassPaneVisible = false;
if (oldGlassPane != null) {
isGlassPaneVisible = oldGlassPane.isVisible();
super.remove(oldGlassPane);
}
if (glassPane != null) {
glassPane.setMixingCutoutShape(new Rectangle());
glassPane.setVisible(isGlassPaneVisible);
super.addImpl(glassPane, null, 0);
}
this.glassPane = glassPane;
firePropertyChange("glassPane", oldGlassPane, glassPane);
revalidate();
repaint();
}
So, JLayer's glass pane is always initially invisible, due to the bizarre visibility-copying behavior in `setGlassPane`. Easy once you know what's going on, but the documentation doesn't *tell* you what's going on. On the contrary, the only vaguely relevant thing it says is "with visibility set to true". Only digging in the source code reveals the truth.
Problems here:
* `createGlassPane()` method: The wording says the glass pane is visible by default, which is *technically* correct but misleading. Also, the wording very much makes it sound like it is designed to be overridden by subclasses, but JLayer is final!! So the only reason for the method to be public is to manually call it, but the documentation doesn't suggest why one should ever need to do so. (I can make my own JPanel, thank you very much.)
* `setGlassPane` method: Why does it copy the visibility of the old glass pane? Why does it assume the glass pane should be invisible by default? WHY ISN'T THAT BIZARRE VISIBILITY-COPYING BEHAVIOR DOCUMENTED AT ALL? THAT IS ABSOLUTELY POINT-BLANK NOT OKAY. When I tried creating my own JPanel, manually forced it visible, and manually set it as the glass pane, it AGAIN got quietly forced invisible because of this bizarre visibility-copying behavior.
* Unspecified: What is the intended use of the glass pane? It can be guessed that the JLayer glass pane behaves similarly to the JRootPane glass pane (i.e., components on the glass pane are painted above other components), but it doesn't technically say that. It doesn't say that anywhere.
* Unspecified: Is the glass pane painted at all by the default LayerUI class, or must we subclass (as suggested by the class documentation) and implement that painting ourselves? (That was another one of the things I tried.)
* Unspecified: Is the glass pane *only* for painting over the view (no), or can components on the glass pane also receive input events? (Yes) Can glass pane components receive keyboard focus? (Yes) Can they interact with drag and drop? (Yes) Those are good features and should be documented!
* Incomplete and broken tutorial: The official JLayer tutorial at https://docs.oracle.com/javase%2Ftutorial%2Fuiswing%2F%2F/misc/jlayer.html doesn't mention the glass pane whatsoever. Also, all the images on that page are 404; I had to go get it from the Wayback Machine.
* No other official documentation ever refers to the JLayer glass pane functionality or describes what it does in any way. The sum and total documentation for this feature is that it's "a new JPanel with visibility set to true and opacity set to false", and it "can be null". Hopelessly incomplete and inadequate!