JFrame Glasspane也在JDialog上,但不应该

我有一个带有Glasspane的JFrame(未修饰)。 这个框架打开一个JDialog(也是未修饰的,也有一个glassPane)并隐藏自己(setVisible(false))。 Glasspanes使用.setGlassPane()设置。 对话框以Frame为所有者打开。

GlassPane扩展了JPanel并实现了AWTEventListener。 我用它来调整框架和对话框的大小,因此它知道它的父级(框架/对话框) – 这称为“目标”。

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(); } } 

在“target.getLocationOnScree”,我得到一个IllegalComponentStateException,当隐藏JFrame并点击JDialog时。 它说“组件必须在屏幕上显示以确定其位置”。 这是因为JFrame的GlassPane获取事件。 但JDialog的Glasspane应该得到它。 我认为,JFrame的Glasspane就在JDialog的前面。 但为什么?

谢谢你的帮助!

编辑:

这是一个例子:

 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()); } } } } 

查看源代码,您只需将frame的玻璃窗格注册到AWTListener。 现在,从表面上看,这似乎并不是一件坏事。 AWTListener将被通知系统中的所有鼠标事件,但实际接收事件的GlassPane实例只会知道frame

基本上,这意味着dialogGlas永远不会收到任何事件,因为它没有注册。

首先,您需要将frameGlasdialogGlas注册为侦听器。

其次,你不应该试图“猜测”目标。 MouseEvent (实际上是所有事件)都有一个源。 您应该将源与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()); } } } } } } 

现在,我不知道你使用MouseListener遇到的问题是它们是贪婪的,它们会阻止事件级联到它们注册的组件之外。