我有一个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
而不是设置为图层,但没有效果。
答案 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);