• category: swing folder: JWindowFocus title: JWindow内にフォーカス可能なコンポーネントを配置する tags: [JWindow, Focus, JFrame, JPopupMenu] author: aterai pubdate: 2021-02-22T08:23:09+09:00 description: JWindowや装飾なしのJFrame、JPopupMenuなどにフォーカス可能なコンポーネントを配置するテストを実行します。 image: https://drive.google.com/uc?id=1tjnD9mtXy7CD07S9aW8kNU7FyC25yk00

概要

JWindowや装飾なしのJFrameJPopupMenuなどにフォーカス可能なコンポーネントを配置するテストを実行します。

サンプルコード

JButton button4 = new JButton("JWindow(owner)");
button4.addActionListener(e -> {
  JButton b = (JButton) e.getSource();
  resetEditor(editor, b);
  Point p = b.getLocation();
  p.y += b.getHeight();
  SwingUtilities.convertPointToScreen(p, b.getParent());
  Window window = new JWindow(SwingUtilities.getWindowAncestor(b));
  window.setFocusableWindowState(true);
  window.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
  // window.setAlwaysOnTop(true);
  window.add(editor);
  window.pack();
  window.setLocation(p);
  window.setVisible(true);
  editor.requestFocusInWindow();
});
View in GitHub: Java, Kotlin

解説

  • JPopupMenu
    • JPopupMenu内にフォーカス可能なコンポーネントとしてJTextAreaを配置
    • JFrameのタイトルバーなどをクリックすると自動的にJPopupMenuが非表示になる
    • JPopupMenu内に配置した子コンポーネントのJTextAreaからJPopupMenuが開けない
    • JFrame内にポップアップするLightWeightPopupJPopupMenu#pack()を実行すると子のJTextAreaからフォーカスが移動してしまうのでJTextArea#requestFocusInWindow()で再設定する必要がある
    • JFrame外にポップアップするHeavyWeightPopupJPopupMenu#pack()を実行すると一瞬親JFrameタイトルバーの描画などが乱れる
button1.addActionListener(e -> {
  JButton b = (JButton) e.getSource();
  resetEditor(editor, b);
  JPopupMenu popup = new JPopupMenu();
  popup.setBorder(BorderFactory.createEmptyBorder());
  popup.add(editor);
  popup.pack();
  Point p = b.getLocation();
  p.y += b.getHeight();
  popup.show(this, p.x, p.y);
  editor.requestFocusInWindow();
});
  • JFrame#setUndecorated(true)
    • JFrame#setUndecorated(true)でタイトルバーなどの装飾を非表示にしたJFrameにフォーカス可能なコンポーネントとしてJTextAreaを配置
    • JFrameがアクティブWindowでなくなるためグローバルフォーカスが外れて親JFrameのタイトルバーの描画などが変化する
    • JTextArea外をクリックして編集終了と合わせてJFrameを閉じる場合、親JFrameMouseListenerComponentListenerを追加する必要がある
      • JFrameのタイトルバーをクリックしてもそのイベントを取得する方法がない?ため、その動作でJTextAreaを閉じることができない
JButton button2 = new JButton("JFrame#setUndecorated(true)");
button2.addActionListener(e -> {
  JButton b = (JButton) e.getSource();
  resetEditor(editor, b);
  JFrame window = new JFrame();
  window.setUndecorated(true);
  window.setAlwaysOnTop(true);
  window.add(editor);
  window.pack();
  Point p = b.getLocation();
  p.y += b.getHeight();
  SwingUtilities.convertPointToScreen(p, b.getParent());
  window.setLocation(p);
  window.setVisible(true);
  editor.requestFocusInWindow();
});
  • JWindow()
    • JWindowにフォーカス可能なコンポーネントとしてJTextAreaを配置
    • JFrameを指定していないので非表示のJFrameが親フレームになり、JWindowに配置したコンポーネントがフォーカスを取得できない
    • JWindow#setFocusableWindowState(true)を指定しても効果がない?
    • 非表示のJFrameが別途表示された後(このサンプルではbutton2button4が実行された後)ならマウスでJTextAreaの文字列を選択することなどが可能になる
JButton button3 = new JButton("JWindow()");
button3.addActionListener(e -> {
  JButton b = (JButton) e.getSource();
  resetEditor(editor, b);
  Window window = new JWindow();
  window.setFocusableWindowState(true);
  window.setAlwaysOnTop(true);
  window.add(editor);
  window.pack();
  Point p = b.getLocation();
  p.y += b.getHeight();
  SwingUtilities.convertPointToScreen(p, b.getParent());
  window.setLocation(p);
  window.setVisible(true);
  editor.requestFocusInWindow();
});
  • JWindow(owner)
    • 表示中の親JFrameを所有フレームにしてJWindowを作成し、これにフォーカス可能なコンポーネントとしてJTextAreaを配置
    • JFrameがアクティブWindowのままになるのでそのタイトルバーの描画などは変化しない
    • JTextArea外をクリックして編集終了と合わせてJWindowを閉じる場合、親JFrameMouseListenerComponentListenerを追加する必要がある
      • 装飾なしのJFrameと同様に親JFrameのタイトルバーをクリックしてもそのイベントを取得する方法がない?ため、その動作でJTextAreaを閉じることができない

参考リンク

コメント