JFrame Glasspane 也在 JDialog 之上,但不应该
本教程将介绍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"处,当 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());
}
}
}
}
推荐答案
查看源代码,您只需要将 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
的问题是它们是贪婪的,它们阻止事件级联超出它们注册的组件.
好了关于JFrame Glasspane 也在 JDialog 之上,但不应该的教程就到这里就结束了,希望趣模板源码网找到的这篇技术文章能帮助到大家,更多技术教程可以在站内搜索。