简体   繁体   English

JFrame Glasspane也位于JDialog之上,但不应

[英]JFrame Glasspane is also over JDialog but shouldn't

I have a JFrame (undecorated) with a Glasspane. 我有一个带有Glasspane的JFrame(未装饰)。 This Frame opens a JDialog (also undecorated and has also a glassPane) and hides itself (setVisible(false)). 此框架打开一个JDialog(也未装饰,也具有glassPane)并隐藏自身(setVisible(false))。 The Glasspanes are set with .setGlassPane(). Glasspanes使用.setGlassPane()设置。 The Dialog is opened with the Frame as owner. 对话框以框架作为所有者打开。

The GlassPane extends a JPanel and implements AWTEventListener. GlassPane扩展了JPanel并实现了AWTEventListener。 I use it for resizing the Frames and Dialogs, so it knows it's parent (the Frame/Dialog) - this is called "target". 我使用它来调整“框架”和“对话框”的大小,因此它知道它是父项(“框架/对话框”)-这称为“目标”。

The Events inside the GlassPane are handled like this: GlassPane内部的事件按以下方式处理:

public void eventDispatched(AWTEvent event) {

  if (target instanceof JFrame) {
     e = SwingUtilities.convertMouseEvent(
     ((MouseEvent) event).getComponent(),
     (MouseEvent) event, ((JFrame) target).getGlassPane());
  } else if (target instanceof JDialog) {
     e = SwingUtilities.convertMouseEvent(
     ((MouseEvent) event).getComponent(),
     (MouseEvent) event, this);
  }


  if (e.getID() == MouseEvent.MOUSE_PRESSED) {
    this.startPos = target.getLocationOnScreen();
  }
}

At "target.getLocationOnScree" I get an IllegalComponentStateException, when the JFrame is hidden and I click on the JDialog. 在隐藏JFrame并单击JDialog时,在“ target.getLocationOnScree”处收到IllegalComponentStateException。 It says "component must be showing on the screen to determine its location". 它说:“必须在屏幕上显示组件才能确定其位置”。 This is because the GlassPane of the JFrame gets the event. 这是因为JFrame的GlassPane获得了事件。 But the Glasspane of the JDialog should get it. 但是JDialog的Glasspane应该可以得到它。 I think, the Glasspane of the JFrame is in front of the JDialog. 我认为,JFrame的Glasspane位于JDialog的前面。 But why? 但为什么?

Thanks for helping! 感谢您的帮助!

Edit: 编辑:

Here is an example: 这是一个例子:

import java.awt.AWTEvent;
import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;

import javax.swing.JDialog;
import javax.swing.JFrame;



public class Main {




    static JFrame frame;
static JDialog dialog;


public static void main(String[] args) {

    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);
    AWTEventListener al = (AWTEventListener) frameGlas;
    Toolkit.getDefaultToolkit().addAWTEventListener(
            al,
            AWTEvent.MOUSE_MOTION_EVENT_MASK
                    | AWTEvent.MOUSE_EVENT_MASK);
    dialogGlas.setVisible(true);
    dialog.setVisible(true);
}


}


import java.awt.AWTEvent;
import java.awt.Point;
import java.awt.Window;
import java.awt.event.AWTEventListener;
import java.awt.event.MouseEvent;

import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

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;

    }



    public void eventDispatched(AWTEvent event) {
        if (event instanceof MouseEvent) {

            MouseEvent originalEvent = (MouseEvent) event;

            MouseEvent e = originalEvent;
        if (target instanceof JDialog) {
                e = SwingUtilities.convertMouseEvent(
                        ((MouseEvent) event).getComponent(),
                        (MouseEvent) event, this);
            }


            if (e.getID() == MouseEvent.MOUSE_PRESSED) {

                Point p  = target.getLocationOnScreen();
                System.out.println(p.getX());
            }
        }

        }



}

Looking at you source code, you only ever register the frame 's glass pane to the AWTListener. 查看您的源代码,您只需将frame的玻璃窗格注册到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 ... AWTListener将收到系统中所有鼠标事件的通知,但是实际接收到该事件的GlassPane实例将只知道该frame ...

Basically, this means that the dialogGlas will never receive any events, as it's not registered. 基本上,这意味着dialogGlas将永远不会收到任何事件,因为它尚未注册。

First, you need to register both the frameGlas and dialogGlas as listeners. 首先,您需要将frameGlasdialogGlas都注册为侦听器。

Second, you shouldn't be trying to "guess" the target. 其次,您不应该试图“猜测”目标。 MouseEvent (in fact all events) have a source. MouseEvent (实际上是所有事件)都有一个来源。 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... 您应该将源与target进行比较,以便仅在事件发生在您感兴趣的组件上时才对事件做出反应...

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. 现在,让我MouseListener是, MouseListener存在的问题是它们MouseListener贪婪,它们可以防止事件级联超出其注册的组件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM