1

我正在尝试编写代码,该代码利用 aJLayer来阻止事件进入被层装饰的组件。但是,我想不出办法来做到这一点。

这是一个 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) {

    }
    }
}

我搜索了一些开发人员试图完全按照我正在做的事情的示例,而我找到的最佳答案是该线程上的最后一篇文章之一。基本上,建议是InputEventeventDispatched. LayerUI在我的示例中,我尝试这样做(当blockInput标志设置为 时true),但它不会阻止输入进入Canvas-"Mouse clicked on canvas"...消息仍被打印。但是,"Mouse clicked on layer"...没有打印,因此使用该事件似乎只会阻止事件JLayerCanvas. 作为绝望的尝试,我也尝试在没有运气的情况下消耗MouseEvent内部processMouseEvent

我担心问题可能是因为Canvas是 AWT 组件,而不是轻量级的 Swing 组件。不幸的是,它必须是Canvas我正在编写的应用程序的 AWT。

有没有人设法阻止输入事件进入由 装饰的重量级组件JLayer

4

1 回答 1

1

您的图层似乎适用于JComponent,例如JPanel. 另请参阅混合重量级和轻量级组件以及如何使用 JLayer 类装饰组件

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);
        }
    }
}
于 2014-08-01T21:03:03.647 回答