我有一个 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);
但问题是,这个变暗的 Pane 没有捕获任何事件,我仍然可以按下框架上的按钮。我还尝试使用 AWTEventListener
来消耗此框架的所有事件,但还有另一个问题:有时我需要显示模式对话框进行一些确认,并且模式对话框的事件也被消耗(我可以不要按任何按钮)。当然,我可以使用一些技巧,例如在框架上方使用透明窗口
而不是变暗 Pane
,或者在以下位置使用大量if-else
语句AWTEventListener
,但我正在寻找一些漂亮的解决方案(如果有的话)。
提前致谢。
UPD:
我还尝试将 Mouse and Key Listeners
添加到分层面板,但出现了一个新问题:如果使用 JDialog
而不是 JFrame
,分层面板的 KeyListener
不会捕获 ESC
按键,对话框将被处理。
UPD2:
我尝试了 frame.setGlassPane(darkeningPane)
而不是设置为图层,但没有效果。
最佳答案
通过添加一个简单的组件作为JLayeredPane
的层来拦截事件是不可能的。看来很多开发者并没有意识到这一点。事件通常会直接分派(dispatch)到包含鼠标事件坐标的最深子组件,或者在按键事件忽略父级的情况下分派(dispatch)到聚焦组件,更不用说甚至不是目标组件的父级的层了。
幸运的是,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);
关于java - 我希望我的 JLayeredPane 能够捕获所有事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25501039/