我正在尝试编写利用JLayer
来阻止事件进入由该层装饰的组件的代码。但是,我无法找到一种方法来做到这一点。
Here is a SSCCE 。这是一个pastebin链接,因为当我尝试使用它时,代码插入总是会破坏格式。
public class Window extends JFrame{
private static boolean blockInput = true;
private CustomCanvas canvas = new CustomCanvas();
public static void main(String[] args) {
new Window().setVisible(true);
}
public Window() {
canvas.addMouseListener(canvas);
LayerUI<Canvas> layerUI = new CanvasLayerUI();
JLayer<Canvas> canvasLayer = new JLayer<Canvas>(canvas, layerUI);
add(canvasLayer);
setSize(800, 600);
}
private class CanvasLayerUI extends LayerUI<Canvas> {
@Override
public void eventDispatched(AWTEvent e, JLayer<? extends Canvas> l) {
if (blockInput) {
if (e instanceof InputEvent) {
((InputEvent) e).consume();
}
} else {
super.eventDispatched(e, l);
}
}
@Override
public void installUI(JComponent c) {
super.installUI(c);
if (c instanceof JLayer) {
JLayer<?> layer = (JLayer<?>) c;
layer.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK);
}
}
@Override
protected void processMouseEvent(MouseEvent e, JLayer<? extends Canvas> l) {
super.processMouseEvent(e, l);
if (e.getID() == MouseEvent.MOUSE_CLICKED) {
System.out.println("Mouse click on layer: " + e.getPoint());
}
}
}
private class CustomCanvas extends Canvas implements MouseListener {
@Override
public void mouseClicked(MouseEvent e) {
System.out.println("Mouse click on canvas: " + e.getPoint());
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
}
我搜索了一些开发人员尝试做我正在做的事情的例子,我发现的最佳答案是 this thread 上的最后一篇文章之一。 。基本上,建议是在 LayerUI
的 eventDispatched
方法中使用 InputEvent
。在我的示例中,我尝试这样做(当 blockInput
标志设置为 true
时),但它不会阻止输入进入 Canvas
- 仍然打印 “Mouse clicked on canvas”...
消息。但是,“鼠标单击图层”...
不会打印,因此使用事件似乎只会阻止事件在 JLayer
内处理,但我需要它们不要进入 Canvas
。作为一次孤注一掷的尝试,我还尝试在 processMouseEvent
中使用 MouseEvent
,但没有成功。
我担心这个问题可能是因为 Canvas
是一个 AWT 组件,而不是一个轻量级的 Swing 组件。不幸的是,对于我正在编写的应用程序来说,它必须是一个 AWT Canvas
。
有没有人设法从由 JLayer
装饰的重量级组件中获取 block 输入事件?
最佳答案
您的图层似乎可以与 JComponent
配合使用,例如 JPanel
。另请参阅Mixing Heavyweight and Lightweight Components和How to Decorate Components with the JLayer Class .
import java.awt.AWTEvent;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLayer;
import javax.swing.JPanel;
import javax.swing.plaf.LayerUI;
public class MyWindow extends JFrame {
private boolean blockInput = true;
private CustomPanel panel = new CustomPanel();
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
new MyWindow().setVisible(true);
});
}
public MyWindow() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
LayerUI<JPanel> layerUI = new CanvasLayerUI();
JLayer<JPanel> canvasLayer = new JLayer<>(panel, layerUI);
add(canvasLayer);
pack();
setLocationRelativeTo(null);
}
private class CanvasLayerUI extends LayerUI<JPanel> {
@Override
public void eventDispatched(AWTEvent e, JLayer<? extends JPanel> l) {
if (blockInput) {
if (e instanceof InputEvent) {
((InputEvent) e).consume();
}
} else {
super.eventDispatched(e, l);
}
}
@Override
public void installUI(JComponent c) {
super.installUI(c);
if (c instanceof JLayer) {
JLayer<?> layer = (JLayer<?>) c;
layer.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK);
}
}
@Override
protected void processMouseEvent(MouseEvent e, JLayer<? extends JPanel> l) {
super.processMouseEvent(e, l);
if (e.getID() == MouseEvent.MOUSE_CLICKED) {
System.out.println("Mouse click on layer: " + e.getPoint());
}
}
}
private class CustomPanel extends JPanel {
public CustomPanel() {
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
System.out.println("Mouse click on canvas: " + e.getPoint());
}
});
}
@Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
}
}
关于java - 使用 JLayer 阻止对 Canvas 的输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25087035/