JWindow内にフォーカス可能なコンポーネントを配置する
Total: 1689
, Today: 2
, Yesterday: 1
Posted by aterai at
Last-modified:
概要
JWindow
や装飾なしのJFrame
、JPopupMenu
などにフォーカス可能なコンポーネントを配置するテストを実行します。
Screenshot
Advertisement
サンプルコード
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
内にポップアップするLightWeightPopup
でJPopupMenu#pack()
を実行すると子のJTextArea
からフォーカスが移動してしまうのでJTextArea#requestFocusInWindow()
で再設定する必要がある - 親
JFrame
外にポップアップするHeavyWeightPopup
でJPopupMenu#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
を閉じる場合、親JFrame
にMouseListener
やComponentListener
を追加する必要がある- 親
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.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
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
が別途表示された後(このサンプルではbutton2
やbutton4
が実行された後)ならマウスで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.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
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
を閉じる場合、親JFrame
にMouseListener
やComponentListener
を追加する必要がある- 装飾なしの
JFrame
と同様に親JFrame
のタイトルバーをクリックしてもそのイベントを取得する方法がない?ため、その動作でJTextArea
を閉じることができない
- 装飾なしの
JWindow#setAlwaysOnTop(true)
を設定していると別アプリケーションのウィンドウが重なってもその手前にセルエディタが表示されることになるので、代わりにWindow#setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE)
を設定して回避
- 表示中の親
参考リンク
- How to Use the Focus Subsystem (The Java™ Tutorials > Creating a GUI With JFC/Swing > Using Other Swing Features)
- JTextAreaとJFrameで幅固定、文字列の折り返し、親枠外まで高さ拡大可能なセルエディタを作成する