Представьте две общие ситуации: JDialog (или JFrame), которая закрывается на VK_ESCAPE (устанавливается как привязка клавиш к корневой панели) и внутренняя JPopupMenu, которая также должна закрываться на ESC. Проблема в том, что нажатие escape всегда закрывает диалог - событие, если всплывающее окно видно. По-видимому, всплывающее окно даже не получает ключевое событие, поэтому оно не может быть использовано всплывающим окном. Есть ли способ заставить это работать правильно, так что в первом ESC-событии всплывающее окно закрывается, а во втором диалог закрывается? Кстати: он работает с JComboBox, который по умолчанию закрывается при нажатии escape.Как включить ESC-Close для JPopupMenu, если основное окно закрывается на ESC?
2
A
ответ
4
Нахождение общего решения было немного сложной задачей. Мы должны учитывать, когда:
- используется облегченный всплывающее окно
- тяжеловес всплывающее окно используется
я решил, что в обоих случаях корневая панель на самом деле имеет фокус, когда ключ побег нажат.
В первом случае я просто просматриваю корневую панель, чтобы увидеть, добавлен ли JPopupMenu в графический интерфейс. Если это так, то мы можем просто закрыть всплывающее окно.
Во втором случае создается окно, в котором содержится JPopupMenu, поэтому я выполняю поиск, чтобы увидеть, отображается ли видимое пользовательское всплывающее окно. Если да, то я удаляю окно.
Если ни один из указанных выше двух случаев не является истинным, вы можете просто закрыть диалоговое окно.
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);
}
}
Вам необходимо скачать Swing Utils класс.
спасибо! Прекрасно работает! – tigger