JFrame Glasspane 也在 JDialog 之上,但不应该

本教程将介绍JFrame Glasspane 也在 JDialog 之上,但不应该的处理方法,这篇教程是从别的地方看到的,然后加了一些国外程序员的疑问与解答,希望能对你有所帮助,好了,下面开始学习吧。

JFrame Glasspane 也在 JDialog 之上,但不应该 教程 第1张

问题描述

我有一个带有 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 永远不会收到任何事件,因为它没有注册.

首先,您需要将 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 的问题是它们是贪婪的,它们阻止事件级联超出它们注册的组件.

好了关于JFrame Glasspane 也在 JDialog 之上,但不应该的教程就到这里就结束了,希望趣模板源码网找到的这篇技术文章能帮助到大家,更多技术教程可以在站内搜索。