• category: swing folder: ComboBoxItemCopy title: JComboBoxのItemをキー入力やJPopupMenuでコピーする tags: [JComboBox, JPopupMenu, ActionMap, InputMap] author: aterai pubdate: 2018/11/19T16:40:06+09:00 description: JComboBoxのItemをキー入力やJPopupMenuを使用してコピーします。 image: https://drive.google.com/uc?id=1NdGJia5hxUObZKEOuG1aS83TzDZvfjOpXQ

概要

JComboBoxItemをキー入力やJPopupMenuを使用してコピーします。

サンプルコード

JComboBox<String> combo1 = new JComboBox<>(makeModel(5));
Action copy = new AbstractAction() {
  @Override public void actionPerformed(ActionEvent e) {
    JComboBox<?> combo = (JComboBox<?>) e.getSource();
    Optional.ofNullable(combo.getSelectedItem()).ifPresent(text -> {
      Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
      Transferable contents = new StringSelection(Objects.toString(text));
      clipboard.setContents(contents, null);
      System.out.println(text);
    });
  }
};
ActionMap am = combo1.getActionMap();
am.put(COPY_KEY, copy);
int modifiers = InputEvent.CTRL_DOWN_MASK;
KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_C, modifiers);
InputMap im = combo1.getInputMap(JComponent.WHEN_FOCUSED);
im.put(keyStroke, COPY_KEY);
JPopupMenu popup = new JPopupMenu();
popup.add(COPY_KEY).addActionListener(e -> {
  Object o = popup.getInvoker();
  Container c = o instanceof JComboBox ? (Container) o
    : SwingUtilities.getAncestorOfClass(JComboBox.class, (Component) o);
  if (c instanceof JComboBox) {
    JComboBox<?> combo = (JComboBox<?>) c;
    Action a = combo.getActionMap().get(COPY_KEY);
    a.actionPerformed(new ActionEvent(combo, e.getID(), e.getActionCommand()));
    // KeyEvent keyEvent = new KeyEvent(combo, 0, 0, 0, 0, 'C');
    // SwingUtilities.notifyAction(a, keyStroke, keyEvent, combo, modifiers);
  }
});
combo1.setComponentPopupMenu(popup);
View in GitHub: Java, Kotlin

解説

  • Default:
    • デフォルトでは編集不可のJComboBoxCtrl+Cなどのキー入力でのコピー機能はない
  • Editable: false, JPopupMenu, Ctrl+C
    • 編集不可のJComboBoxActionMapInputMapを使用してCtrl+Cキーで現在選択中のアイテム文字列をコピー可能に設定
    • JComboBox#setComponentPopupMenu(...)ActionMapに追加したコピーイベントを呼び出せるよう設定
      • JComboBoxのボタン上でJPopupMenuを呼び出すとJPopupMenu#getInvoker()JButtonが返るので注意が必要
  • Editable: true, JPopupMenu, Ctrl+C
    • JComboBox#getEditor().getEditorComponent()で取得したJTextFieldJTextField#setComponentPopupMenu(...)でコピーなどを実行するJPopupMenuを設定
    • JTextFieldはデフォルトでCtrl+Cキーなどでのコピーが可能

参考リンク

コメント