概要

JList間でコピー&ペーストによるアイテムの複製・移動を行います。

サンプルコード

class ListPopupMenu extends JPopupMenu {
  private final JMenuItem cutItem;
  private final JMenuItem copyItem;
  protected ListPopupMenu(JList<?> list) {
    super();
    Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
    TransferHandler handler = list.getTransferHandler();
    cutItem = add("cut");
    cutItem.addActionListener(e -> {
      handler.exportToClipboard(list, clipboard, TransferHandler.MOVE);
    });
    copyItem = add("copy");
    copyItem.addActionListener(e -> {
      handler.exportToClipboard(list, clipboard, TransferHandler.COPY);
    });
    add("paste").addActionListener(e -> {
      handler.importData(list, clipboard.getContents(null));
    });
    addSeparator();
    add("clearSelection").addActionListener(e -> list.clearSelection());
  }

  @Override public void show(Component c, int x, int y) {
    if (c instanceof JList) {
      boolean isSelected = !((JList<?>) c).isSelectionEmpty();
      cutItem.setEnabled(isSelected);
      copyItem.setEnabled(isSelected);
      super.show(c, x, y);
    }
  }
}
View in GitHub: Java, Kotlin

解説

上記のサンプルでは、TransferHandlerを使ったJListのドラッグ&ドロップによる並べ替えを元にし、ドラッグ&ドロップに加えてクリップボード経由でのアイテム移動や複製が可能になるようなListItemTransferHandlerを作成して、JListに設定しています。

  • TransferHandlerを使ったJListのドラッグ&ドロップによる並べ替えではTransferHandler.TransferSupport#isDrop()falseの場合はインポート不可(TransferHandler#canImport(...) == false)とし、またActionMapでもキーボードによるコピーなどを無効に設定している
  • 一方このサンプルではTransferHandler.TransferSupport#isDrop()falseの場合、以下のようにキーボード入力やJPopupMenuからのカット、コピー、ペーストと判断してJList#getSelectedIndex()で取得した位置にアイテムを貼り込むように変更
    private static int getIndex(TransferHandler.TransferSupport info) {
      JList<?> target = (JList<?>) info.getComponent();
      int index; // = dl.getIndex();
      if (info.isDrop()) { // Mouse Drag & Drop
        System.out.println("Mouse Drag & Drop");
        TransferHandler.DropLocation tdl = info.getDropLocation();
        if (tdl instanceof JList.DropLocation) {
          index = ((JList.DropLocation) tdl).getIndex();
        } else {
          index = target.getSelectedIndex();
        }
      } else { // Keyboard Copy & Paste
        index = target.getSelectedIndex();
      }
      DefaultListModel<?> listModel = (DefaultListModel<?>) target.getModel();
      // boolean insert = dl.isInsert();
      int max = listModel.getSize();
      // int index = dl.getIndex();
      index = index < 0 ? max : index; // If it is out of range, it is appended to the end
      index = Math.min(index, max);
      return index;
    }
    

参考リンク

コメント