JFrame Glasspane is also over JDialog but shouldn't

后端 未结 1 961
无人共我
无人共我 2021-01-26 09:27

I have a JFrame (undecorated) with a Glasspane. This Frame opens a JDialog (also undecorated and has also a glassPane) and hides itself (setVisible(false)). The Glasspanes are s

1条回答
  •  一整个雨季
    2021-01-26 10:12

    Looking at you source code, you only ever register the frame's glass pane to the AWTListener. Now, on the surface, this doesn't seem like a bad thing. The AWTListener will be notified of ALL the mouse events in the system, but the instance of GlassPane that is actually receiving the events will only know about the frame...

    Basically, this means that the dialogGlas will never receive any events, as it's not registered.

    First, you need to register both the frameGlas and dialogGlas as listeners.

    Second, you shouldn't be trying to "guess" the target. MouseEvent (in fact all events) have a source. You should be comparing the source with the target so you can react to events only when they occur on components you're interested in...

    import java.awt.AWTEvent;
    import java.awt.Component;
    import java.awt.EventQueue;
    import java.awt.Point;
    import java.awt.Toolkit;
    import java.awt.Window;
    import java.awt.event.AWTEventListener;
    import java.awt.event.MouseEvent;
    import javax.swing.JDialog;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class Main {
    
        static JFrame frame;
        static JDialog dialog;
    
        public static void main(String[] args) {
            new Main();
        }
    
        public Main() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
    
                    frame = new JFrame();
                    frame.setSize(600, 600);
                    GlassPane frameGlas = new GlassPane(frame);
                    frame.setGlassPane(frameGlas);
                    frame.setVisible(true);
    
                    frameGlas.setVisible(true);
                    dialog = new JDialog(frame);
    
                    dialog.setSize(100, 100);
                    GlassPane dialogGlas = new GlassPane(dialog);
                    dialog.setGlassPane(dialogGlas);
                    dialogGlas.setVisible(true);
                    dialog.setVisible(true);
    
                    // Register a listener for the frameGlas
                    Toolkit.getDefaultToolkit().addAWTEventListener(
                            frameGlas,
                            AWTEvent.MOUSE_MOTION_EVENT_MASK
                            | AWTEvent.MOUSE_EVENT_MASK);
                    // Register a listener for the dialogGlas
                    Toolkit.getDefaultToolkit().addAWTEventListener(
                            dialogGlas,
                            AWTEvent.MOUSE_MOTION_EVENT_MASK
                            | AWTEvent.MOUSE_EVENT_MASK);
                }
            });
        }
    
        public class GlassPane extends JPanel implements AWTEventListener {
    
            private static final long serialVersionUID = 5110857185182004819L;
            private final Window target;
    
            public GlassPane(Window target) {
                super(null);
                this.target = target;
    
            }
    
            @Override
            public void eventDispatched(AWTEvent event) {
                if (event instanceof MouseEvent) {
    
                    MouseEvent originalEvent = (MouseEvent) event;
    
                    MouseEvent e = originalEvent;
                    Component source = e.getComponent();
                    System.out.println("Source: " + source);
                    System.out.println("Target: " + target);
                    if (target != null && target.equals(source)) {
                        e = SwingUtilities.convertMouseEvent(
                                ((MouseEvent) event).getComponent(),
                                (MouseEvent) event, this);
    
                        if (e.getID() == MouseEvent.MOUSE_PRESSED) {
    
                            Point p = target.getLocationOnScreen();
                            System.out.println(p.getX());
                        }
                    }
                }
            }
        }
    }
    

    Now, off the top of my head, the problem you're having with MouseListener is that they are greedy, they prevent the events from cascading beyond the component they are registered on.

    0 讨论(0)
提交回复
热议问题