Pergunta

Imagine duas situações comuns combinado:Um JDialog(ou JFrame), que fecha em VK_ESCAPE (definir como chave de ligação na raiz do painel) e um interior JPopupMenu que é suposto para fechar ESC bem.O problema é:pressionar escape sempre fecha a caixa de diálogo evento, se o pop-up é visível.Aparentemente, o pop-up não receber o evento-chave para que ele não pode ser consumido pelo pop-up.Existe alguma maneira de obter esta funcionando corretamente, de modo que no primeiro ESC-evento de pop-up está fechado e na segunda, a caixa de diálogo fecha?A propósito:Ele funciona com um JComboBox, que, por padrão, fecha-se quando a fuga é pressionado.

Foi útil?

Solução

Encontrar uma solução genérica foi um pouco de um desafio.Precisamos considerar quando:

  1. um peso leve pop-up é usado
  2. um peso pesado, pop-up é usado

Eu determinou que, em ambos os casos, a raiz do painel, na verdade, tem o foco quando for premida a tecla escape.

No primeiro caso, eu só procurar a raiz do painel para ver se um JPopupMenu foi adicionado à interface gráfica.Se é assim, então podemos simplesmente fechar a pop-up.

No segundo caso, a Janela é criada para conter o JPopupMenu para eu fazer uma pesquisa para ver se um visível personalizado Janela pop-up é exibida.Se é assim, então posso descartar a janela.

Se nenhum dos anteriores dois casos é verdade, você pode simplesmente fechar a caixa de 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 );
    }
}

Também será necessário baixar o Balanço Utils de classe.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top