本文介绍了JFrame Glasspane也在JDialog上,但不应该的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a JFrame (undecorated) with a Glasspane.This Frame opens a JDialog (also undecorated and has also a glassPane) and hides itself (setVisible(false)).The Glasspanes are set with .setGlassPane().The Dialog is opened with the Frame as owner.

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

The GlassPane extends a JPanel and implements AWTEventListener.I use it for resizing the Frames and Dialogs, so it knows it's parent (the Frame/Dialog) - this is called "target".

事件GlassPane内部的处理方式如下:

The Events inside the GlassPane are handled like this:

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的前面。但为什么?

At "target.getLocationOnScree" I get an IllegalComponentStateException, when the JFrame is hidden and I click on the JDialog. It says "component must be showing on the screen to determine its location". This is because the GlassPane of the JFrame gets the event. But the Glasspane of the JDialog should get it. I think, the Glasspane of the JFrame is in front of the JDialog. But why?

感谢您的帮助!

编辑:

这是一个例子:

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

        }



}


推荐答案

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

Looking at you source code, you only ever register the frame's glass pane to the 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...

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

Basically, this means that the dialogGlas will never receive any events, as it's not registered.

首先,你需要注册 frameGlas dialogGlas 作为侦听器。

First, you need to register both the frameGlas and dialogGlas as listeners.

其次,你不应该试图猜测目标。 MouseEvent (实际上所有事件)都有一个来源。您应该将源与目标进行比较,这样您只有在对您感兴趣的组件上发生事件时才能对事件作出反应...

Second, you shouldn't be trying to "guess" the target. MouseEvent (in fact all events) have a source. 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...

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 的问题是他们贪婪,他们阻止事件发生级联超出他们注册的组件。

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.

这篇关于JFrame Glasspane也在JDialog上,但不应该的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-12 07:02