scrollrecttovisible rootpane java jframe mouseevent jdialog glasspane

rootpane - scrollrecttovisible java



JFrame Glasspane también ha superado JDialog pero no debería (1)

Al mirar su código fuente, solo registra el panel de cristal del frame en el AWTListener. Ahora, en la superficie, esto no parece algo malo. Se notificará al AWTListener de TODOS los eventos del mouse en el sistema, pero la instancia de GlassPane que realmente recibe los eventos solo sabrá sobre el frame ...

Básicamente, esto significa que dialogGlas nunca recibirá ningún evento, ya que no está registrado.

Primero, necesita registrar tanto frameGlas como dialogGlas como oyentes.

En segundo lugar, no deberías tratar de "adivinar" el objetivo. MouseEvent (de hecho, todos los eventos) tienen una fuente. Deberías estar comparando la fuente con el target para que puedas reaccionar a los eventos solo cuando ocurran en los componentes que te interesen ...

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

Ahora, fuera de mi cabeza, el problema que estás teniendo con MouseListener es que son codiciosos, evitan que los eventos caigan en cascada más allá del componente en el que están registrados.

Tengo un JFrame (sin decoración) con un Glasspane. Este cuadro abre un JDialog (también sin decorar y también tiene un panel de cristal) y se oculta (setVisible (falso)). Los Glasspanes se establecen con .setGlassPane (). El cuadro de diálogo se abre con el cuadro como propietario.

GlassPane amplía un JPanel e implementa AWTEventListener. Lo uso para cambiar el tamaño de los marcos y cuadros de diálogo, por lo que sabe que es padre (el Marco / Diálogo) - esto se llama "objetivo".

Los eventos dentro del GlassPane se manejan así:

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

En "target.getLocationOnScree" obtengo una IllegalComponentStateException, cuando el JFrame está oculto y hago clic en el JDialog. Dice que "el componente debe mostrarse en la pantalla para determinar su ubicación". Esto se debe a que GlassPane of the JFrame obtiene el evento. Pero el Glasspane de JDialog debería obtenerlo. Creo que Glasspane of the JFrame está frente al JDialog. ¿Pero por qué?

¡Gracias por ayudar!

Editar:

Aquí hay un ejemplo:

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