java - 使用 JLayer 阻止对 Canvas 的输入

标签 java swing canvas awt jlayer

我正在尝试编写利用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 上的最后一篇文章之一。 。基本上,建议是在 LayerUIeventDispatched 方法中使用 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 ComponentsHow 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/

相关文章:

java - Guice:如何在没有注入(inject)器或使用构造函数注入(inject)的情况下获取单例实例

java - 从具有nativeQuery true J​​PARepository的@Query注释获取两列

Java volatile变量影响其他非volatile变量的内存一致性

Java Swing 范围 slider 用户界面

java - 仅调整 Java Swing 组件一部分的大小

java - 访问已经创建JFrame

javascript - 为什么我的 Canvas 仅在刷新时加载?

javascript - 如何在 Canvas 元素上绘制视频?

java - Microsoft JET 数据库引擎的数据库驱动程序

javascript - jQuery 是否支持 Canvas ?