我有一个带有Glasspane的JFrame(未修饰)。 这个框架打开一个JDialog(也是未修饰的,也有一个glassPane)并隐藏自己(setVisible(false))。 Glasspanes使用.setGlassPane()设置。 打开对话框,框架为所有者。
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”中,当隐藏JFrame并点击JDialog时,我得到一个IllegalComponentStateException。它说“必须在屏幕上显示组件以确定其位置”。这是因为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());
}
}
}
}
答案 0 :(得分:1)
查看源代码,您只需将frame
的玻璃窗格注册到AWTListener。现在,从表面上看,这似乎并不是一件坏事。 AWTListener
将通知系统中的所有鼠标事件,但实际接收事件的GlassPane
实例只会知道frame
...
基本上,这意味着dialogGlas
永远不会收到任何事件,因为它没有注册。
首先,您需要将frameGlas
和dialogGlas
注册为侦听器。
其次,你不应该试图“猜测”目标。 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
他们贪婪,他们阻止事件超出他们注册的组件。