当前位置: 首页 > 面试题库 >

JFrame Glasspane也位于JDialog之上,但不应

双浩涆
2023-03-14
问题内容

我有一个带有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();
  }
}

在隐藏JFrame并单击JDialog时,在“
target.getLocationOnScree”处收到一个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实际上接收到该事件的html" target="_blank">实例只会知道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是,他们遇到的问题是贪婪,它们阻止事件层叠到所注册的组件之外。



 类似资料:
  • 我认为spring-boot-starter-security中的某个模块与log4j冲突,但我不知道是哪一个。 我的gradle依赖性如下:

  • 当我试图运行我的项目时,我得到了标题中发现的错误。我已经阅读了关于此错误的其他线程,并找到了一个解决方案,该解决方案消除了该错误,但杀死了我所有的日志记录。 线程“main”java.lang.IllegalArgumentException中的异常:LoggerFactory不是LoggerContext,但Logback位于类路径上。删除Logback或竞争实现(类org.slf4j.impl

  • 我有上面的代码,它的用途是在执行某些代码时向用户显示消息(代码执行大约需要5-10秒,我不想让用户认为程序冻结)。 问题是,添加到对话框中的JLabel根本没有出现。确切地说,无论我在对话框中添加什么,它都不会出现。 然而,如果我将JDialog设置为modal(将true作为最后一个参数添加到上面的构造函数中),它就会出现,但是我想要执行的代码不会运行,直到对话框关闭,违背了它的目的。 由于代码

  • 我不知道我的代码或WPF是否有问题,但问题是:我想创建一个小程序,你可以在画布上用光标绘制。我有一个简单的WPF窗口: 这是后台代码: 我能做的是:https://www.dropbox.com/s/7moq4p8f8f409b3/wpf_canvas.png 当光标位于画布之外时,为什么要调用StackPan\u MouseMove? 这是可执行文件,您可以在其中注意到这种行为:https://

  • 特性: 可修改CSS来统一定制UI; 通过参数设置标题,高度,宽度,窗口显示的HTML内容; 一个页面同时只能显示一个窗口; 窗口显示需要指定一个页面上的对象做为窗口显示做置定位,这样窗口会出现在哪个东西的下面,就像下拉列表一样. 不能拖动(我们不需要这样的功能); 可以点击窗口之外的任意区域来关闭窗口,或是点右上角的关闭按钮. 演示地址: http://huacnlee.github.com/jdialog/

  • 问题内容: 我在另一个div内有两个div,我想使用css将一个子div放在父div的右上角,另一个子div放在父div的底下。即,我想对两个子div使用绝对定位,但是将它们相对于父div而不是页面定位。我怎样才能做到这一点? 范例html: 问题答案: 这工作,因为手段类似“使用,,,来定位自己相对于谁拥有最近的祖先或”。 因此,我们使have 和子代都有,然后使用和定位子代。