Pregunta

Imaginemos dos situaciones comunes combinados: Una JDialog (o JFrame) que cierra el VK_ESCAPE (juego como clave de enlace en el panel raíz) y un JPopupMenu interior que se supone que es de cerca CES también. El problema es: presionando escape siempre se cierra el diálogo - si el evento emergente es visible. Al parecer, el emergente ni siquiera recibir el evento clave para que no pueda ser consumido por la ventana emergente. ¿Hay alguna manera de conseguir este trabajo correctamente, de manera que en el primer caso el CES-emergente se cierra y en el segundo se cierra el diálogo? Por cierto: No funciona con un JComboBox, que se cierra por defecto cuando se presiona de escape

.
¿Fue útil?

Solución

Búsqueda de una solución genérica era un poco un desafío. Debemos tener en cuenta cuando:

  1. Se utiliza una ventana emergente peso ligero
  2. Se utiliza una ventana emergente de peso pesado

Me determinado que en ambos casos el panel raíz en realidad tiene el foco cuando se pulsa la tecla de escape.

En el primer caso, acabo de buscar en el panel de la raíz para ver si un JPopupMenu se ha añadido a la interfaz gráfica de usuario. Si es así, entonces podemos simplemente cierre la ventana emergente.

En el segundo caso se crea una ventana para contener el JPopupMenu así que hacer una búsqueda para ver si aparece una ventana emergente personalizado visible. Si es así, entonces me deshago de la ventana.

Si ninguno de los dos casos anteriores es cierto, entonces puede simplemente cerrar el diálogo.

import java.awt.*;
import java.awt.event.*;
import java.util.List;
import javax.swing.*;
import javax.swing.event.*;

public class DialogEscape extends JDialog
{
    private JPopupMenu popup;

    public DialogEscape()
    {
        popup = new JPopupMenu();
        popup.add( new JMenuItem("SubMenuA") );
        popup.add( new JMenuItem("SubMenuB") );
        popup.add( new JMenuItem("SubMenuC") );
        popup.add( new JMenuItem("SubMenuD") );

        String[] items = { "Select Item", "Color", "Shape", "Fruit" };
        JComboBox comboBox = new JComboBox( items );
        add(comboBox, BorderLayout.NORTH);

        JTextField textField = new JTextField("Right Click For Popup");
        textField.setComponentPopupMenu(popup);
        add(textField);

        KeyStroke escapeKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false);
        Action escapeAction = new AbstractAction()
        {
            public void actionPerformed(ActionEvent e)
            {
                boolean openPopup = false;
                Component c = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();

                //  Check if light weight popup is being used

                List<JPopupMenu> popups = SwingUtils.getDescendantsOfType(JPopupMenu.class, (Container)c, true);

                for (JPopupMenu p: popups)
                {
                    p.setVisible( false );
                    openPopup = true;
                }

                //  Check if a heavy weight popup is being used

                Window window = SwingUtilities.windowForComponent(c);
                Window[] windows = window.getOwnedWindows();

                for (Window w: windows)
                {
                    if (w.isVisible()
                    &&  w.getClass().getName().endsWith("HeavyWeightWindow"))
                    {
                        openPopup = true;
                        w.dispose();
                    }
                }

                //  No popups so close the Window

                if (! openPopup)
//                  SwingUtilities.windowForComponent(c).setVisible(false);
                    SwingUtilities.windowForComponent(c).dispose();
            }
        };

        getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(escapeKeyStroke, "ESCAPE");
        getRootPane().getActionMap().put("ESCAPE", escapeAction);
    }

    public static void main(String[] args)
    {
        String laf = null;
        laf = "javax.swing.plaf.metal.MetalLookAndFeel";
//      laf = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
//      laf = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";

        try { UIManager.setLookAndFeel(laf); }
        catch (Exception e2) { System.out.println(e2); }

        JDialog dialog = new DialogEscape();
        dialog.setDefaultCloseOperation( HIDE_ON_CLOSE );
        dialog.setSize(200, 200);
        dialog.setLocationRelativeTo(null);
        dialog.setVisible( true );
    }
}

También tendrá que descargar el oscilación clase Utilidades .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top