JPopupMenuを開く前に対象となるJTextFieldにFocusを移動する
Total: 3381, Today: 1, Yesterday: 2
Posted by aterai at
Last-modified:
Summary
JTextFieldなどに設定したJPopupMenuをマウスの右クリックで開くとき、そのJTextComponentにFocusを移動し文字列を全選択します。
Screenshot

Advertisement
Source Code Examples
class TextComponentPopupMenu extends JPopupMenu {
private final Action cutAction = new DefaultEditorKit.CutAction();
private final Action copyAction = new DefaultEditorKit.CopyAction();
private final Action pasteAction = new DefaultEditorKit.PasteAction();
protected TextComponentPopupMenu() {
super();
add(cutAction);
add(copyAction);
add(pasteAction);
}
@Override public void show(Component c, int x, int y) {
System.out.println(c.getClass().getName() + ": " + c.getName());
if (c instanceof JTextComponent) {
JTextComponent tc = (JTextComponent) c;
tc.requestFocusInWindow();
boolean isSelected = tc.getSelectionStart() != tc.getSelectionEnd();
if (tc instanceof JTextField && !tc.isFocusOwner() && !isSelected) {
tc.selectAll();
isSelected = true;
}
cutAction.setEnabled(isSelected);
copyAction.setEnabled(isSelected);
super.show(c, x, y);
}
}
}
View in GitHub: Java, KotlinDescription
Default setComponentPopupMenuJTextField#setComponentPopupMenu(...)でJTextFieldにJPopupMenuを設定- 別の
JTextComponentにフォーカスがある状態でこのJTextField内を右クリックしてJPopupMenuを表示してもフォーカスは前のJTextComponentに残る new DefaultEditorKit.PasteAction()で生成した貼り込みアクションなどはフォーカスのあるJTextComponentに対して実行されるので、前のJTextComponentに文字列が張り込まれる
Override JPopupMenu#show(...)JTextField#setComponentPopupMenu(...)でJTextFieldにJPopupMenuを設定JPopupMenu#show(...)をオーバーライドしてJPopupMenuを開く前にComponent#requestFocusInWindow()メソッドを実行し、このJTextFieldにフォーカスを移動するPopupMenuListener#popupMenuWillBecomeVisible(...)、またはMouseListener#mousePressed(...)をオーバーライドする方法でも構わない
- フォーカス移動と合わせて
JTextField内を右クリックしてJPopupMenuを開く場合は内部の文字列を全選択する処理を追加
JPopupMenu does not open???- 編集可能に設定した
JComboBoxのJTextFieldにマウスクリックでフォーカスを移動しても、他コンポーネントのJPopupMenuが開いたままになるバグ(仕様?)があるため、JTextField#setComponentPopupMenu(...)で追加したJPopupMenuを開くことができない - JDK-8044493 Clicking on an editable JComboBox leaves JPopupMenus and other menus open - Java Bug System
- Prevent popup menu dismissal | Exploding Pixels
textField.putClientProperty("doNotCancelPopup", null);で回避可能だが、エディタをマウスでクリックするとJComboBoxのドロップダウンリストも閉じるようになるJComboBox<String> combo5 = new JComboBox<>(new String[] {"000", "111", "222"}); combo5.setEditable(true); combo5.setComponentPopupMenu(popup2); JTextField textField5 = (JTextField) combo5.getEditor().getEditorComponent(); textField5.putClientProperty("doNotCancelPopup", null);
- 編集可能に設定した
addMouseListener- 編集可能に設定した
JComboBoxのJTextFieldにMouseListenerを追加し、マウスでクリックされたら一旦すべてのJPopupMenuを閉じるよう設定- ただし、自身の親の
JComboBoxが開いたドロップダウンリストは除外する - 参考: MenuSelectionManagerですべてのJPopupMenuを取得する
- ただし、自身の親の
- 編集可能に設定した
JComboBox<String> combo4 = new JComboBox<>(new String[] {"addMouseListener", "111", "222"});
combo4.setEditable(true);
JTextField textField4 = (JTextField) combo4.getEditor().getEditorComponent();
textField4.setComponentPopupMenu(popup2);
textField4.setName("textField4");
textField4.addMouseListener(new MouseAdapter() {
@Override public void mousePressed(MouseEvent e) {
System.out.println("Close all JPopupMenu");
// https://ateraimemo.com/Swing/GetAllPopupMenus.html
for (MenuElement m : MenuSelectionManager.defaultManager().getSelectedPath()) {
if (combo4.isPopupVisible()) {
continue;
} else if (m instanceof JPopupMenu) {
((JPopupMenu) m).setVisible(false);
}
}
}
});
Reference
- DefaultEditorKitでポップアップメニューからコピー
- MenuSelectionManagerですべてのJPopupMenuを取得する
- JTextField内のテキストをすべて選択
- JDK-8044493 Clicking on an editable JComboBox leaves JPopupMenus and other menus open - Java Bug System