2013-05-19 2 views
0

У меня есть JFrame (undecorated) с Glasspane. Эта рамка открывает JDialog (также undecorated и имеет также стеклянную панель) и прячется (setVisible (false)). Стеклянные стекла установлены с .setGlassPane(). Диалог открывается с помощью Рамы как владельца.JFrame Glasspane также над JDialog, но не должен

GlassPane расширяет JPanel и реализует AWTEventListener. Я использую его для изменения размеров фреймов и диалогов, поэтому он знает, что это родительский (Frame/Dialog) - это называется «цель».

В События внутри 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» я получаю IllegalComponentStateException, когда JFrame скрыта и я нажимаю на JDialog. В нем говорится, что «компонент должен показывать на экране, чтобы определить его местоположение». Это связано с тем, что GlassPane JFrame получает событие. Но Glasspane JDialog должен получить это. Я думаю, Glasspane JFrame находится перед JDialog. Но почему?

Спасибо за помощь!

Edit:

Вот пример:

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

Это похоже на то, что ваш слушатель мыши использует рамку в качестве цели вместо диалога, но если вы не представите рабочий пример своей проблемы, не смогли бы помочь. Другой вопрос, который приходит на ум, - почему вы просто не используете MouseListener? – MadProgrammer

+0

Я добавил рабочий пример с двумя кланами «Главная» и «Стеклянная панель». Извините, я мог бы проигнорировать «setUndecorated». Я не использую MouseListener, потому что это противоречит некоторым другим вещам. Честно говоря, я не совсем понимаю, почему. Но я помню, что у меня было больше проблем с MouseListeners, чем с GlassPane. – user1894572

ответ

0

Глядя на вас исходный код, вы только когда-либо зарегистрировать стеклянной плоскости frame «s к 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 заключается в том, что они жадные, они предотвращают каскадирование событий вне компонента, на котором они зарегистрированы.

+0

Спасибо большое! Это было очень полезно. Оно работает. Тот факт, что я только зарегистрировал стек GlassPane для слушателя, был ошибкой. У меня были оба GlassPanes. Чтобы упростить пример, я хотел удалить слушателя кадра, но случайно удалил прослушиватель диалога. В любом случае - еще раз спасибо. – user1894572

+0

Пока мы его работаем;) – MadProgrammer