VK_ESCAPE (ルート ペインでキー バインディングとして設定) で閉じる JDialog(または JFrame) と、ESC でも閉じるはずの内部 JPopupMenu という 2 つの一般的な状況を組み合わせて想像してみてください。問題は、エスケープを押すと常にダイアログが閉じられることです - ポップアップが表示されている場合のイベント。どうやら、ポップアップはキーイベントを受け取ることさえできないため、ポップアップで消費することはできません。最初のESCイベントでポップアップが閉じられ、2番目にダイアログが閉じるように、これを正しく機能させる方法はありますか? ちなみに、デフォルトではエスケープが押されると閉じるJComboBoxで動作します。
1936 次
2 に答える
5
一般的な解決策を見つけるのは少し大変でした。次の場合を考慮する必要があります。
- 軽量のポップアップが使用されます
- 重いポップアップが使用されています
どちらの場合も、エスケープ キーを押すとルート ペインに実際にフォーカスがあることがわかりました。
最初のケースでは、ルート ペインを検索して、JPopupMenu が GUI に追加されているかどうかを確認します。その場合は、ポップアップを閉じるだけです。
2 番目のケースでは、JPopupMenu を含む Window が作成されるため、表示可能なカスタム ポップアップ Window が表示されているかどうかを検索します。もしそうなら、私は窓を処分します。
上記の 2 つのケースのいずれにも当てはまらない場合は、ダイアログを閉じることができます。
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クラスもダウンロードする必要があります。
于 2010-09-29T04:33:42.033 に答える