我希望我的JLayeredPane能够捕获所有事件

时间:2014-08-26 08:14:44

标签: java swing

我有一个JFrame,我想在某些加载过程中禁用它。为此,我创建了DisablingLayeredPane类:

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();
    }
}

在加载过程开始时,我调用

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

但问题是,这个变暗的窗格没有捕捉到任何事件,我仍然可以按下我的框架上的按钮。我也试过AWTEventListener来消耗这个帧的所有事件,但还有另一个问题:有时我需要显示模态对话框以进行一些确认,并且模态对话框的事件也被消耗(我不能按任何按钮)。当然,我可以使用一些技巧,例如在我的框架上使用transparent window代替darkening pane,或者在if-else使用很多AWTEventListener语句,但我正在寻找一个一些漂亮的解决方案,如果有的话。

提前致谢。

UPD: 我还尝试将Mouse and Key Listeners添加到分层面板,但是有一个新问题:如果使用JDialog代替JFrame,则分层面板的KeyListener将无法捕获{按键和对话框将会处理{1}}。

UPD2: 我尝试ESC而不是设置为图层,但没有效果。

1 个答案:

答案 0 :(得分:2)

通过在JLayeredPane方面添加一个简单的组件作为图层来拦截事件是不可能的。似乎很多开发人员都没有意识到这一点。事件通常直接发送到包含鼠标事件坐标的最深子组件,或者在忽略父项的键事件情况下发送到聚焦组件,而不是说甚至不是目标组件父项的图层。

值得庆幸的是,Java 7中添加了一个组件,它为您提供了复杂的技巧JLayer,而不是与JLayeredPane混淆。

以下是如何使用它的示例:

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);