概要

JFrameJDialogなどのWindowを開いたときに、デフォルトでフォーカスを持つコンポーネントを指定します。

サンプルコード

EventQueue.invokeLater(new Runnable() {
  @Override public void run() {
    field.requestFocusInWindow();
  }
});
view all

解説

上記のサンプルでは、JTextFieldがデフォルトのフォーカスを持つように、JComponent#requestFocusInWindow()メソッドを使用しています。

JComponent#requestFocusInWindow()メソッドは、チュートリアル(How to Use the Focus Subsystem)にあるように、JFrame#pack()、もしくはJFrame#setSize(...)などでリサイズされた後(フォーカスを取得するコンポーネントのサイズが決まった後)で実行する必要があります。このため、このサンプルではEventQueue.invokeLater(...)を使って、待ち状態のすべてのイベントが処理された一番後で実行するようにしています。


以下のように、FocusTraversalPolicyWindowListenerを使う方法でも、同様にデフォルトのフォーカスを持つコンポーネントを指定することが出来ます。

  • FocusTraversalPolicyを使用
    • FocusTraversalPolicyを設定して、最初にフォーカスの当たるコンポーネントを指定(JDK 1.4.0以降)
frame.setFocusTraversalPolicy(new LayoutFocusTraversalPolicy() {
  @Override public Component getInitialComponent(Window w) {
    return field;
  }
});
  • WindowListener#windowOpened(...)で、requestFocusInWindow()
    • フレームにWindowListenerを設定して、windowOpened(...)が呼び出されたときに、requestFocusInWindow()を実行
frame.addWindowListener(new WindowAdapter() {
  @Override public void windowOpened(WindowEvent e) {
    field.requestFocusInWindow();
  }
});
  • ComponentListener#componentShown(...)で、requestFocusInWindow()
    • フレームにComponentListenerを設定して、componentShown(...)が呼び出されたとき(=フレームがsetVisible(true)されたとき)に、requestFocusInWindow()を実行
frame.addComponentListener(new ComponentAdapter() {
  @Override public void componentShown(ComponentEvent e) {
    field.requestFocusInWindow();
  }
});
  • KeyboardFocusManager#addPropertyChangeListener(...)で、requestFocusInWindow()
    • KeyboardFocusManagerPropertyChangeListenerを設定して、propertyChange(...)が呼び出され、PropertyNameが、activeWindow、かつPropertyChangeEvent#getNewValue()nullでないときに、requestFocusInWindow()を実行
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
kfm.addPropertyChangeListener(new PropertyChangeListener() {
  @Override public void propertyChange(PropertyChangeEvent e) {
    String prop = e.getPropertyName();
    if ("activeWindow".equals(prop) && e.getNewValue() != null) {
      System.out.println("activeWindow");
      field.requestFocusInWindow();
    }
  }
});

参考リンク

コメント

  • JFrame#getRootPane()#setDefaultButton()は使用方法がよくわからない… -- aterai
  • setDefaultButtonって、Enterしたときに押されたとみなすボタンだったかな…… --
    • ありがとうございます。おかげでようやく理解できました。JTextFieldなどにフォーカスがある状態でEnterキーを入力するとsetDefaultButtonしたボタンが押されるのですね。 -- aterai
    • というわけで、frame.getRootPane().setDefaultButton(eb);を追加してみました。上記のサンプルでは、中央のJTextFieldにフォーカスがある状態で、Enterキーを押すと、EASTボタンが押されたことになります。 -- aterai
    • いつか、DefaultButtonのページを別に作成すること。 -- aterai
    • DefaultButtonの設定に移動。 -- aterai
  • HierarchyListenerを使用する場合のテスト -- aterai