2

I have a JFrame and I want to set it disabled on some loading processes. For that purpose I've created the DisablingLayeredPane class:

public class DisablingLayeredPane extends JPanel {

    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f));
        g2d.setColor(Color.BLACK); // With 0.2f alpha it looks like light gray
        g2d.fillRect(0, 0, getWidth(), getHeight());
        g2d.dispose();
    }
}

On the loading process start, I call

frame.getLayeredPane().add(darkeningPane, JLayeredPane.MODAL_LAYER);

But the problem is, this darkening pane does not catch any events, I still can press buttons on my frame. I've also tried AWTEventListener to consume all of events for this frame, but there is another issue: sometimes I need to show modal dialog for some confirmation, and events for modal dialog are consumed too (I can't press any button). Of course, I can use some tricks like using transparent window above my frame instead darkening pane, or use a lot of if-else statements at AWTEventListener, but I'm looking for a some beautiful solution, if any.

Thanks in advance.

UPD: I've also tried to add Mouse and Key Listeners to layered panel, but there is a new issue: if use JDialog instead JFrame, the KeyListener of layered panel would not catch ESC key pressing and dialog would dispose.

UPD2: I've tried frame.setGlassPane(darkeningPane) instead setting as layer, but there is no effect.

SeniorJD
  • 6,946
  • 4
  • 36
  • 53
  • Usually, the way to implement this is using the JFrame's glass pane. – ethanfar Aug 26 '14 at 08:54
  • I've tried `frame.setGlassPane(darkeningPane)`, events are still passed to frame components. – SeniorJD Aug 26 '14 at 09:24
  • That's probably because in Swing, transparent panels do not receive events by default. You should read a good tutorial on glass panes (there are plenty of those online), since what you're trying to do is quite common. – ethanfar Aug 26 '14 at 10:07
  • What do you mean by 'transparent'? I don't call `setOpaque(false)`, I adjust the `alpha` while painting. – SeniorJD Aug 26 '14 at 10:12
  • You didn't have to. `JLayeredPane` extends `JComponent` which by default is not opaque. – ethanfar Aug 26 '14 at 10:31
  • AFAIK only focusable JComponents can to react with KeyEvents, KeyBindings by default havent this issue, required to set Focus to desired JCOmponent or container, [the shadowing issue with GlassPane to test with](http://stackoverflow.com/q/8715807/714968), (flamewar, hot_potato_game) voting to close as off_topics, because there isn't any effort to show me(us) something that make me sence – mKorbel Aug 26 '14 at 11:28
  • for classes compiled in Java7 to use JLayer – mKorbel Aug 26 '14 at 11:30
  • @camickr here I linked your DisabledGlassPane used in my question – mKorbel Aug 26 '14 at 11:31
  • @mKorbel sorry, I don't understand why do you vote as off_topics. May be it is unclear, but not off_topics, I think. – SeniorJD Aug 26 '14 at 12:05
  • e.g. how did your set that, why it doesn't works, whats another setting for ([because your JPanel returns zero Dimension](http://stackoverflow.com/a/25505225/714968)) and another 5-6 important code lines, dot :-) – mKorbel Aug 26 '14 at 12:08
  • this question is about massve down_voting and should be closed immediatelly by users that understand this issue and to required an SSCCE/MCVE for ..., answers by default equals OPs effort in question, simple I'm missing that here – mKorbel Aug 26 '14 at 12:10
  • my JPanel does not return zero dimension. Where did you get this? Why do you try to resolve not the same issue I've asked for? `this question is about massve down_voting and should be closed immediatelly` What? Are you drunk? :) – SeniorJD Aug 26 '14 at 12:35

1 Answers1

3

It is impossible to intercept events by adding a simple component as a layer in terms of JLayeredPane. It seems that a lot of developers are not aware of this. Events are usually dispatched directly to the deepest child component containing the coordinates of a mouse event or to the focused component in case of a key event ignoring the parents, not to speak layers that are not even parents of the target component.

Thankfully there was a component added in Java 7 which does the complicated trick for you, JLayer, not to confuse with JLayeredPane.

Here is an example of how to use it:

JFrame f=new JFrame("Disabling via JLayer");
final JLayer<JTree> layer = new JLayer<JTree>(new JTree(), new LayerUI<JTree>() {
  @Override
  public void eventDispatched(AWTEvent e, JLayer<? extends JTree> l) {
    if(e instanceof InputEvent) ((InputEvent)e).consume();
  }
  @Override
  public void paint(Graphics g, JComponent c) {
    super.paint(g, c);
    Graphics2D g2d = (Graphics2D) g.create();
    g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f));
    g2d.setColor(Color.BLACK);
    g2d.fillRect(0, 0, c.getWidth(), c.getHeight());
    g2d.dispose();
  }
});
f.setContentPane(layer);
layer.setLayerEventMask(~0);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
Holger
  • 285,553
  • 42
  • 434
  • 765
  • Is it necessary to set `JLayer` as `ContentPane`? – SeniorJD Aug 26 '14 at 12:41
  • No, it must be the parent of the component (hierarchy) you want to disable. So it’s natural to use it as content pane if you want to disable the entire frame’s content. But it doesn’t have to. – Holger Aug 26 '14 at 12:43
  • Thanks, I'll try `JLayer` and let you know if it would work for me – SeniorJD Aug 26 '14 at 12:50